From ee45763ceb9a72daed079be90a07c2cb8826e560 Mon Sep 17 00:00:00 2001 From: driesva Date: Fri, 2 Jun 2023 09:11:49 +0200 Subject: [PATCH 01/80] fix: Slow RabbitMQ message polling Configurable RabbitMQ polling in order that more messages can be obtained from the queue during a poll. Fixes #8445 --- .../src/main/resources/thingsboard.yml | 1 + .../rabbitmq/TbRabbitMqConsumerTemplate.java | 32 ++++- .../queue/rabbitmq/TbRabbitMqSettings.java | 2 + .../TbRabbitMqConsumerTemplateTest.java | 128 ++++++++++++++++++ 4 files changed, 156 insertions(+), 7 deletions(-) create mode 100644 common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index 96e409373e..b0b8923dcc 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1117,6 +1117,7 @@ queue: automatic_recovery_enabled: "${TB_QUEUE_RABBIT_MQ_AUTOMATIC_RECOVERY_ENABLED:false}" connection_timeout: "${TB_QUEUE_RABBIT_MQ_CONNECTION_TIMEOUT:60000}" handshake_timeout: "${TB_QUEUE_RABBIT_MQ_HANDSHAKE_TIMEOUT:10000}" + max_poll_messages: "${TB_QUEUE_RABBIT_MQ_MAX_POLL_MESSAGES:1}" queue-properties: rule-engine: "${TB_QUEUE_RABBIT_MQ_RE_QUEUE_PROPERTIES:x-max-length-bytes:1048576000;x-message-ttl:604800000}" core: "${TB_QUEUE_RABBIT_MQ_CORE_QUEUE_PROPERTIES:x-max-length-bytes:1048576000;x-message-ttl:604800000}" diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplate.java b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplate.java index e073a46a05..4891f65e30 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplate.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplate.java @@ -20,6 +20,8 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.GetResponse; +import java.util.ArrayList; +import java.util.Collection; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.queue.TbQueueAdmin; @@ -31,7 +33,6 @@ import org.thingsboard.server.queue.common.DefaultTbQueueMsg; import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; @@ -44,6 +45,7 @@ public class TbRabbitMqConsumerTemplate extends AbstractTb private final TbQueueMsgDecoder decoder; private final Channel channel; private final Connection connection; + private final int maxPollMessages; private volatile Set queues; @@ -51,6 +53,7 @@ public class TbRabbitMqConsumerTemplate extends AbstractTb super(topic); this.admin = admin; this.decoder = decoder; + this.maxPollMessages = rabbitMqSettings.getMaxPollMessages(); try { connection = rabbitMqSettings.getConnectionFactory().newConnection(); } catch (IOException | TimeoutException e) { @@ -70,13 +73,19 @@ public class TbRabbitMqConsumerTemplate extends AbstractTb protected List doPoll(long durationInMillis) { List result = queues.stream() .map(queue -> { - try { - return channel.basicGet(queue, false); - } catch (IOException e) { - log.error("Failed to get messages from queue: [{}]", queue); - throw new RuntimeException("Failed to get messages from queue.", e); + List messages = new ArrayList<>(); + for (int i = 0; i < maxPollMessages; i++) { + GetResponse response = doQueuePoll(queue); + if (response == null) { + break; + } + messages.add(response); } - }).filter(Objects::nonNull).collect(Collectors.toList()); + return messages; + }) + .filter(r -> !r.isEmpty()) + .flatMap(Collection::stream) + .collect(Collectors.toList()); if (result.size() > 0) { return result; } else { @@ -84,6 +93,15 @@ public class TbRabbitMqConsumerTemplate extends AbstractTb } } + protected GetResponse doQueuePoll(String queue) { + try { + return channel.basicGet(queue, false); + } catch (IOException e) { + log.error("Failed to get messages from queue: [{}]", queue); + throw new RuntimeException("Failed to get messages from queue.", e); + } + } + @Override protected void doSubscribe(List topicNames) { queues = partitions.stream() diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java index 0273374ddc..fd2977f7cc 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqSettings.java @@ -47,6 +47,8 @@ public class TbRabbitMqSettings { private int connectionTimeout; @Value("${queue.rabbitmq.handshake_timeout:}") private int handshakeTimeout; + @Value("${queue.rabbitmq.max_poll_messages:1}") + private int maxPollMessages; private ConnectionFactory connectionFactory; diff --git a/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java b/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java new file mode 100644 index 0000000000..ab132912fc --- /dev/null +++ b/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java @@ -0,0 +1,128 @@ +/** + * Copyright © 2016-2023 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.queue.rabbitmq; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; +import com.rabbitmq.client.ConnectionFactory; +import com.rabbitmq.client.GetResponse; +import java.nio.charset.StandardCharsets; +import java.util.Set; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; +import org.thingsboard.server.queue.TbQueueAdmin; +import org.thingsboard.server.queue.TbQueueMsgDecoder; +import org.thingsboard.server.queue.common.DefaultTbQueueMsg; + +@ExtendWith(MockitoExtension.class) +class TbRabbitMqConsumerTemplateTest { + + private static final String TOPIC = "some-topic"; + + @Mock + private TbQueueAdmin admin; + + @Mock + private ConnectionFactory connectionFactory; + + @Mock + private TbQueueMsgDecoder decoder; + + @Mock + private Connection connection; + + @Mock + private Channel channel; + + @Mock + private TopicPartitionInfo partition; + + @Mock + private GetResponse getResponse; + + private TbRabbitMqConsumerTemplate consumer; + + private void setUpConsumerWithMaxPollMessages(int maxPollMessages) throws Exception { + when(connectionFactory.newConnection()).thenReturn(connection); + when(connection.createChannel()).thenReturn(channel); + TbRabbitMqSettings settings = new TbRabbitMqSettings(); + settings.setMaxPollMessages(maxPollMessages); + settings.setConnectionFactory(connectionFactory); + + consumer = new TbRabbitMqConsumerTemplate<>(admin, settings, TOPIC, decoder); + when(partition.getFullTopicName()).thenReturn(TOPIC); + consumer.subscribe(Set.of(partition)); + } + + @Test + void pollWithMax5PollMessagesReturnsEmptyListIfNoMessages() throws Exception { + setUpConsumerWithMaxPollMessages(5); + when(channel.basicGet(anyString(), anyBoolean())).thenReturn(null); + + assertThat(consumer.poll(0L)).isEmpty(); + + verify(channel).basicGet(anyString(), anyBoolean()); + } + + @Test + void pollWithMax5PollMessagesReturns5MessagesIfQueueContains5() throws Exception { + setUpConsumerWithMaxPollMessages(5); + when(getResponse.getBody()).thenReturn(newMessageBody()); + when(channel.basicGet(anyString(), anyBoolean())).thenReturn(getResponse); + + assertThat(consumer.poll(0L)).hasSize(5); + + verify(channel, times(5)).basicGet(anyString(), anyBoolean()); + } + + @Test + void pollWithMax1PollMessageReturns1MessageIfQueueContainsMore() throws Exception { + setUpConsumerWithMaxPollMessages(1); + when(getResponse.getBody()).thenReturn(newMessageBody()); + when(channel.basicGet(anyString(), anyBoolean())).thenReturn(getResponse); + + assertThat(consumer.poll(0L)).hasSize(1); + + verify(channel).basicGet(anyString(), anyBoolean()); + } + + @Test + void pollWithMax3PollMessagesReturns2MessagesIfQueueContains2() throws Exception { + setUpConsumerWithMaxPollMessages(3); + when(getResponse.getBody()).thenReturn(newMessageBody()); + when(channel.basicGet(anyString(), anyBoolean())).thenReturn(getResponse, getResponse, null); + + assertThat(consumer.poll(0L)).hasSize(2); + + verify(channel, times(3)).basicGet(anyString(), anyBoolean()); + } + + private byte[] newMessageBody() { + return ("{\"key\": \"" + UUID.randomUUID() + "\"}").getBytes(StandardCharsets.UTF_8); + } + +} \ No newline at end of file From 9efec4755a1d7fd7db4a56f308064e491f30663c Mon Sep 17 00:00:00 2001 From: chenggwang <90715678+chenggwang@users.noreply.github.com> Date: Wed, 27 Sep 2023 23:21:39 +0800 Subject: [PATCH 02/80] CompletableFuture compliant scheduling tasks CompletableFuture compliant scheduling tasks --- .../org/thingsboard/mqtt/MqttHandler.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttHandler.java b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttHandler.java index 21c07a17cd..5bd249ff5c 100644 --- a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttHandler.java +++ b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttHandler.java @@ -15,10 +15,30 @@ */ package org.thingsboard.mqtt; -import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.Future; import io.netty.buffer.ByteBuf; public interface MqttHandler { - - ListenableFuture onMessage(String topic, ByteBuf payload); + /** + * Changing ListenableFuture to Future allows you to choose CompletableFuture, + * which gives developers the freedom to choose the orchestration method. + * CompletableFuture is a newer, more evolved version that eliminates callback hell, + * is easier to use, and comes with the JDK. jdk 1.8 was previously used with the Before JDK1.8, + * use ListenableFuture, after that, it is recommended to use CompletableFuture. + * ListenableFuture It's still written that way.{@link MqttMessageListener#onMessage(topic, payload)} + * public ListenableFuture onMessage(String topic, ByteBuf message) { + * log.info("MQTT message [{}], topic [{}]", message.toString(StandardCharsets.UTF_8), topic); + * events.add(new MqttEvent(topic, message.toString(StandardCharsets.UTF_8))); + * return Futures.immediateVoidFuture(); + * } + * CompletableFuture It's like this. + * public CompletableFuture onMessage(String topic, ByteBuf message) { + * log.info("MQTT message [{}], topic [{}]", message.toString(StandardCharsets.UTF_8), topic); + * events.add(new MqttEvent(topic, message.toString(StandardCharsets.UTF_8))); + * return CompletableFuture.completedFuture(null); + * } + * This change does not affect the system's current use of ListenableFuture so that it is free to choose between ListenableFuture or + * CompletableFuture in new development. + */ + Future onMessage(String topic, ByteBuf payload); } From afb6595de9e1737b5b50e9f3ef068ec0302b7037 Mon Sep 17 00:00:00 2001 From: Jan Hilberath Date: Fri, 26 Jan 2024 20:13:58 +0900 Subject: [PATCH 03/80] Fix debug log message in MqttTransportHandler:exceptionCaught() --- .../thingsboard/server/transport/mqtt/MqttTransportHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index 8360111a54..782c99eb22 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -1017,6 +1017,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement log.debug("[{}][{}][{}] IOException: {}", sessionId, Optional.ofNullable(this.deviceSessionCtx.getDeviceInfo()).map(TransportDeviceInfo::getDeviceId).orElse(null), Optional.ofNullable(this.deviceSessionCtx.getDeviceInfo()).map(TransportDeviceInfo::getDeviceName).orElse(""), + cause.getMessage(), cause); } else if (log.isInfoEnabled()) { log.info("[{}][{}][{}] IOException: {}", sessionId, From 8779c629e7d2fa49ddb92d13bfb7e60ea58c9bb4 Mon Sep 17 00:00:00 2001 From: livk Date: Wed, 31 Jan 2024 14:17:39 +0800 Subject: [PATCH 04/80] fix: fixed the error that the file could not be found after packing --- .../mail/DefaultTbMailConfigTemplateService.java | 2 +- .../java/org/thingsboard/common/util/JacksonUtil.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultTbMailConfigTemplateService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultTbMailConfigTemplateService.java index f45f949fca..66207b5c39 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultTbMailConfigTemplateService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultTbMailConfigTemplateService.java @@ -32,7 +32,7 @@ public class DefaultTbMailConfigTemplateService implements TbMailConfigTemplateS @PostConstruct private void postConstruct() throws IOException { - mailConfigTemplates = JacksonUtil.toJsonNode(new ClassPathResource("/templates/mail_config_templates.json").getFile()); + mailConfigTemplates = JacksonUtil.toJsonNode(new ClassPathResource("/templates/mail_config_templates.json").getInputStream()); } @Override diff --git a/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java b/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java index 53c3860dde..46c76b5a61 100644 --- a/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java +++ b/common/util/src/main/java/org/thingsboard/common/util/JacksonUtil.java @@ -35,6 +35,7 @@ import org.thingsboard.server.common.data.kv.KvEntry; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.Reader; import java.io.Writer; import java.util.Arrays; @@ -182,6 +183,15 @@ public class JacksonUtil { } } + public static JsonNode toJsonNode(InputStream value) { + try { + return value != null ? OBJECT_MAPPER.readTree(value) : null; + } catch (IOException e) { + throw new IllegalArgumentException("The given InputStream value: " + + value + " cannot be transformed to a JsonNode", e); + } + } + public static ObjectNode newObjectNode() { return newObjectNode(OBJECT_MAPPER); } From 689ebd57b3739365320dd082cbcc4f154de888c1 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Fri, 31 May 2024 09:16:38 +0300 Subject: [PATCH 05/80] Fixed creation of profiles with name "default" in case when default profile exists, but was renamed --- .../server/dao/asset/AssetProfileServiceImpl.java | 3 ++- .../server/dao/device/DeviceProfileServiceImpl.java | 3 ++- .../server/dao/service/AssetProfileServiceTest.java | 12 ++++++++++++ .../server/dao/service/DeviceProfileServiceTest.java | 12 ++++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java index 6848c58d5c..12724e1a62 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java @@ -234,8 +234,9 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService Date: Fri, 31 May 2024 15:55:27 +0200 Subject: [PATCH 06/80] set default kafka compression to none, to align it with the ThingsBoard application defaults --- msa/js-executor/config/default.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msa/js-executor/config/default.yml b/msa/js-executor/config/default.yml index 0e15413e31..f5bde183e4 100644 --- a/msa/js-executor/config/default.yml +++ b/msa/js-executor/config/default.yml @@ -34,7 +34,7 @@ kafka: partitions_consumed_concurrently: "1" # (EXPERIMENTAL) increase this value if you are planning to handle more than one partition (scale up, scale down) - this will decrease the latency requestTimeout: "30000" # The default value in kafkajs is: 30000 connectionTimeout: "1000" # The default value in kafkajs is: 1000 - compression: "gzip" # gzip or uncompressed + compression: "none" # gzip or uncompressed topic_properties: "retention.ms:604800000;segment.bytes:52428800;retention.bytes:104857600;partitions:100;min.insync.replicas:1" use_confluent_cloud: false client_id: "kafkajs" #inject pod name to easy identify the client using /opt/kafka/bin/kafka-consumer-groups.sh From 976e1e1e1f463f6474a42aa84b22251bf9918d51 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 24 Jul 2024 13:22:17 +0300 Subject: [PATCH 07/80] Implement TTL for password reset and user activation links; refactoring and improvements --- .../main/data/upgrade/3.7.0/schema_update.sql | 16 ++ .../server/controller/AdminController.java | 6 +- .../server/controller/AuthController.java | 61 ++++--- .../server/controller/BaseController.java | 2 +- .../server/controller/UserController.java | 64 ++++---- .../entitiy/user/DefaultUserService.java | 3 +- .../secret/MobileAppSecretServiceImpl.java | 10 +- .../auth/rest/RestAuthenticationProvider.java | 8 +- .../system/DefaultSystemSecurityService.java | 84 ++-------- .../system/SystemSecurityService.java | 9 +- .../server/controller/AuthControllerTest.java | 151 +++++++++++++----- .../server/dao/user/UserService.java | 6 +- .../common/data/security/UserCredentials.java | 102 ++---------- .../data/security/model/SecuritySettings.java | 25 ++- .../server/dao/model/ModelConstants.java | 2 + .../dao/model/sql/UserCredentialsEntity.java | 17 +- .../DefaultSecuritySettingsService.java | 81 ++++++++++ .../dao/settings/SecuritySettingsService.java | 26 +++ .../server/dao/user/UserServiceImpl.java | 29 +++- .../main/resources/sql/schema-entities.sql | 2 + .../sql/user/JpaUserCredentialsDaoTest.java | 2 + 21 files changed, 417 insertions(+), 289 deletions(-) create mode 100644 dao/src/main/java/org/thingsboard/server/dao/settings/DefaultSecuritySettingsService.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/settings/SecuritySettingsService.java diff --git a/application/src/main/data/upgrade/3.7.0/schema_update.sql b/application/src/main/data/upgrade/3.7.0/schema_update.sql index 6b87dc6dde..a7e4aaeeef 100644 --- a/application/src/main/data/upgrade/3.7.0/schema_update.sql +++ b/application/src/main/data/upgrade/3.7.0/schema_update.sql @@ -14,3 +14,19 @@ -- limitations under the License. -- +-- USER CREDENTIALS UPDATE START + +ALTER TABLE user_credentials ADD COLUMN IF NOT EXISTS activate_token_exp_time BIGINT; +-- Setting 24-hour TTL for existing activation tokens +UPDATE user_credentials SET activate_token_exp_time = cast(extract(EPOCH FROM NOW()) * 1000 AS BIGINT) + 86400000 + WHERE activate_token IS NOT NULL AND activate_token_exp_time IS NULL; + +ALTER TABLE user_credentials ADD COLUMN IF NOT EXISTS reset_token_exp_time BIGINT; +-- Setting 24-hour TTL for existing password reset tokens +UPDATE user_credentials SET reset_token_exp_time = cast(extract(EPOCH FROM NOW()) * 1000 AS BIGINT) + 86400000 + WHERE reset_token IS NOT NULL AND reset_token_exp_time IS NULL; + +UPDATE admin_settings SET json_value = (json_value::jsonb || '{"userActivationTokenTtl":24,"passwordResetTokenTtl":24}'::jsonb)::varchar + WHERE key = 'securitySettings'; + +-- USER CREDENTIALS UPDATE END diff --git a/application/src/main/java/org/thingsboard/server/controller/AdminController.java b/application/src/main/java/org/thingsboard/server/controller/AdminController.java index 65903a4dec..46eeefd951 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AdminController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AdminController.java @@ -73,6 +73,7 @@ import org.thingsboard.server.common.data.sync.vc.VcUtils; import org.thingsboard.server.config.annotations.ApiOperation; import org.thingsboard.server.dao.audit.AuditLogService; import org.thingsboard.server.dao.settings.AdminSettingsService; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.jwt.settings.JwtSettingsService; import org.thingsboard.server.service.security.auth.oauth2.CookieUtils; @@ -109,6 +110,7 @@ public class AdminController extends BaseController { private final SmsService smsService; private final AdminSettingsService adminSettingsService; private final SystemSecurityService systemSecurityService; + private final SecuritySettingsService securitySettingsService; private final JwtSettingsService jwtSettingsService; private final JwtTokenFactory tokenFactory; private final EntitiesVersionControlService versionControlService; @@ -167,7 +169,7 @@ public class AdminController extends BaseController { @ResponseBody public SecuritySettings getSecuritySettings() throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ); - return checkNotNull(systemSecurityService.getSecuritySettings()); + return checkNotNull(securitySettingsService.getSecuritySettings()); } @ApiOperation(value = "Update Security Settings (saveSecuritySettings)", @@ -179,7 +181,7 @@ public class AdminController extends BaseController { @Parameter(description = "A JSON value representing the Security Settings.") @RequestBody SecuritySettings securitySettings) throws ThingsboardException { accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE); - securitySettings = checkNotNull(systemSecurityService.saveSecuritySettings(securitySettings)); + securitySettings = checkNotNull(securitySettingsService.saveSecuritySettings(securitySettings)); return securitySettings; } diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index f95dfcb648..86301cfb6a 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -26,9 +26,10 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; @@ -48,6 +49,7 @@ import org.thingsboard.server.common.data.security.model.JwtPair; import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; import org.thingsboard.server.config.annotations.ApiOperation; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails; import org.thingsboard.server.service.security.model.ActivateUserRequest; @@ -75,6 +77,7 @@ public class AuthController extends BaseController { private final JwtTokenFactory tokenFactory; private final MailService mailService; private final SystemSecurityService systemSecurityService; + private final SecuritySettingsService securitySettingsService; private final RateLimitService rateLimitService; private final ApplicationEventPublisher eventPublisher; @@ -82,7 +85,7 @@ public class AuthController extends BaseController { @ApiOperation(value = "Get current User (getUser)", notes = "Get the information about the User which credentials are used to perform this REST API call.") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - @RequestMapping(value = "/auth/user", method = RequestMethod.GET) + @GetMapping(value = "/auth/user") public @ResponseBody User getUser() throws ThingsboardException { SecurityUser securityUser = getCurrentUser(); @@ -92,7 +95,7 @@ public class AuthController extends BaseController { @ApiOperation(value = "Logout (logout)", notes = "Special API call to record the 'logout' of the user to the Audit Logs. Since platform uses [JWT](https://jwt.io/), the actual logout is the procedure of clearing the [JWT](https://jwt.io/) token on the client side. ") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - @RequestMapping(value = "/auth/logout", method = RequestMethod.POST) + @PostMapping(value = "/auth/logout") @ResponseStatus(value = HttpStatus.OK) public void logout(HttpServletRequest request) throws ThingsboardException { logLogoutAction(request); @@ -101,8 +104,7 @@ public class AuthController extends BaseController { @ApiOperation(value = "Change password for current User (changePassword)", notes = "Change the password for the User which credentials are used to perform this REST API call. Be aware that previously generated [JWT](https://jwt.io/) tokens will be still valid until they expire.") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") - @RequestMapping(value = "/auth/changePassword", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = "/auth/changePassword") public JwtPair changePassword(@Parameter(description = "Change Password Request") @RequestBody ChangePasswordRequest changePasswordRequest) throws ThingsboardException { String currentPassword = changePasswordRequest.getCurrentPassword(); @@ -125,11 +127,9 @@ public class AuthController extends BaseController { @ApiOperation(value = "Get the current User password policy (getUserPasswordPolicy)", notes = "API call to get the password policy for the password validation form(s).") - @RequestMapping(value = "/noauth/userPasswordPolicy", method = RequestMethod.GET) - @ResponseBody + @GetMapping(value = "/noauth/userPasswordPolicy") public UserPasswordPolicy getUserPasswordPolicy() throws ThingsboardException { - SecuritySettings securitySettings = - checkNotNull(systemSecurityService.getSecuritySettings()); + SecuritySettings securitySettings = checkNotNull(securitySettingsService.getSecuritySettings()); return securitySettings.getPasswordPolicy(); } @@ -137,14 +137,14 @@ public class AuthController extends BaseController { notes = "Checks the activation token and forwards user to 'Create Password' page. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Create Password' page and same 'activateToken' specified in the URL parameters. " + "If token is not valid, returns '409 Conflict'.") - @RequestMapping(value = "/noauth/activate", params = {"activateToken"}, method = RequestMethod.GET) + @GetMapping(value = "/noauth/activate", params = {"activateToken"}) public ResponseEntity checkActivateToken( @Parameter(description = "The activate token string.") @RequestParam(value = "activateToken") String activateToken) { HttpHeaders headers = new HttpHeaders(); HttpStatus responseStatus; UserCredentials userCredentials = userService.findUserCredentialsByActivateToken(TenantId.SYS_TENANT_ID, activateToken); - if (userCredentials != null) { + if (userCredentials != null && !userCredentials.isActivationTokenExpired()) { String createURI = "/login/createPassword"; try { URI location = new URI(createURI + "?activateToken=" + activateToken); @@ -163,8 +163,7 @@ public class AuthController extends BaseController { @ApiOperation(value = "Request reset password email (requestResetPasswordByEmail)", notes = "Request to send the reset password email if the user with specified email address is present in the database. " + "Always return '200 OK' status for security purposes.") - @RequestMapping(value = "/noauth/resetPasswordByEmail", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) + @PostMapping(value = "/noauth/resetPasswordByEmail") public void requestResetPasswordByEmail( @Parameter(description = "The JSON object representing the reset password email request.") @RequestBody ResetPasswordEmailRequest resetPasswordByEmailRequest, @@ -187,7 +186,7 @@ public class AuthController extends BaseController { notes = "Checks the password reset token and forwards user to 'Reset Password' page. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Reset Password' page and same 'resetToken' specified in the URL parameters. " + "If token is not valid, returns '409 Conflict'.") - @RequestMapping(value = "/noauth/resetPassword", params = {"resetToken"}, method = RequestMethod.GET) + @GetMapping(value = "/noauth/resetPassword", params = {"resetToken"}) public ResponseEntity checkResetToken( @Parameter(description = "The reset token string.") @RequestParam(value = "resetToken") String resetToken) { @@ -196,7 +195,7 @@ public class AuthController extends BaseController { String resetURI = "/login/resetPassword"; UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken); - if (userCredentials != null) { + if (userCredentials != null && !userCredentials.isResetTokenExpired()) { if (!rateLimitService.checkRateLimit(LimitedApi.PASSWORD_RESET, userCredentials.getUserId(), defaultLimitsConfiguration)) { return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).build(); } @@ -220,15 +219,12 @@ public class AuthController extends BaseController { "The response already contains the [JWT](https://jwt.io) activation and refresh tokens, " + "to simplify the user activation flow and avoid asking user to input password again after activation. " + "If token is valid, returns the object that contains [JWT](https://jwt.io/) access and refresh tokens. " + - "If token is not valid, returns '404 Bad Request'.") - @RequestMapping(value = "/noauth/activate", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) - @ResponseBody - public JwtPair activateUser( - @Parameter(description = "Activate user request.") - @RequestBody ActivateUserRequest activateRequest, - @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, - HttpServletRequest request) throws ThingsboardException { + "If token is not valid, returns '400 Bad Request'.") + @PostMapping(value = "/noauth/activate") + public JwtPair activateUser(@Parameter(description = "Activate user request.") + @RequestBody ActivateUserRequest activateRequest, + @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, + HttpServletRequest request) { String activateToken = activateRequest.getActivateToken(); String password = activateRequest.getPassword(); systemSecurityService.validatePassword(password, null); @@ -258,18 +254,18 @@ public class AuthController extends BaseController { @ApiOperation(value = "Reset password (resetPassword)", notes = "Checks the password reset token and updates the password. " + "If token is valid, returns the object that contains [JWT](https://jwt.io/) access and refresh tokens. " + - "If token is not valid, returns '404 Bad Request'.") - @RequestMapping(value = "/noauth/resetPassword", method = RequestMethod.POST) - @ResponseStatus(value = HttpStatus.OK) - @ResponseBody - public JwtPair resetPassword( - @Parameter(description = "Reset password request.") - @RequestBody ResetPasswordRequest resetPasswordRequest, - HttpServletRequest request) throws ThingsboardException { + "If token is not valid, returns '400 Bad Request'.") + @PostMapping(value = "/noauth/resetPassword") + public JwtPair resetPassword(@Parameter(description = "Reset password request.") + @RequestBody ResetPasswordRequest resetPasswordRequest, + HttpServletRequest request) throws ThingsboardException { String resetToken = resetPasswordRequest.getResetToken(); String password = resetPasswordRequest.getPassword(); UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken); if (userCredentials != null) { + if (userCredentials.isResetTokenExpired()) { + throw new ThingsboardException("Password reset token expired", ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } systemSecurityService.validatePassword(password, userCredentials); if (passwordEncoder.matches(password, userCredentials.getPassword())) { throw new ThingsboardException("New password should be different from existing!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); @@ -277,6 +273,7 @@ public class AuthController extends BaseController { String encodedPassword = passwordEncoder.encode(password); userCredentials.setPassword(encodedPassword); userCredentials.setResetToken(null); + userCredentials.setResetTokenExpTime(null); userCredentials = userService.replaceUserCredentials(TenantId.SYS_TENANT_ID, userCredentials); User user = userService.findUserById(TenantId.SYS_TENANT_ID, userCredentials.getUserId()); UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail()); diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index f9d1fe7a2f..da956d4fa5 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -178,7 +178,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId; @TbCoreComponent public abstract class BaseController { - private final Logger log = org.slf4j.LoggerFactory.getLogger(getClass()); + protected final Logger log = org.slf4j.LoggerFactory.getLogger(getClass()); /*Swagger UI description*/ diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 1772a64772..c76958dabe 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -21,7 +21,6 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; @@ -130,12 +129,8 @@ public class UserController extends BaseController { private final SystemSecurityService systemSecurityService; private final ApplicationEventPublisher eventPublisher; private final TbUserService tbUserService; - - @Autowired - private EntityQueryService entityQueryService; - - @Autowired - private EntityService entityService; + private final EntityQueryService entityQueryService; + private final EntityService entityService; @ApiOperation(value = "Get User (getUserById)", notes = "Fetch the User object based on the provided User Id. " + @@ -212,7 +207,7 @@ public class UserController extends BaseController { public User saveUser( @Parameter(description = "A JSON value representing the User.", required = true) @RequestBody User user, - @Parameter(description = "Send activation email (or use activation link)" , schema = @Schema(defaultValue = "true")) + @Parameter(description = "Send activation email (or use activation link)", schema = @Schema(defaultValue = "true")) @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, HttpServletRequest request) throws ThingsboardException { if (!Authority.SYS_ADMIN.equals(getCurrentUser().getAuthority())) { user.setTenantId(getCurrentUser().getTenantId()); @@ -231,19 +226,10 @@ public class UserController extends BaseController { @RequestParam(value = "email") String email, HttpServletRequest request) throws ThingsboardException { User user = checkNotNull(userService.findUserByEmail(getCurrentUser().getTenantId(), email)); + accessControlService.checkPermission(getCurrentUser(), Resource.USER, Operation.READ, user.getId(), user); - accessControlService.checkPermission(getCurrentUser(), Resource.USER, Operation.READ, - user.getId(), user); - - UserCredentials userCredentials = userService.findUserCredentialsByUserId(getCurrentUser().getTenantId(), user.getId()); - if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { - String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request); - String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, - userCredentials.getActivateToken()); - mailService.sendActivationEmail(activateUrl, email); - } else { - throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); - } + String activationLink = getActivationLink(user.getId(), request); + mailService.sendActivationEmail(activationLink, email); } @ApiOperation(value = "Get the activation link (getActivationLink)", @@ -252,23 +238,13 @@ public class UserController extends BaseController { @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @RequestMapping(value = "/user/{userId}/activationLink", method = RequestMethod.GET, produces = "text/plain") @ResponseBody - public String getActivationLink( - @Parameter(description = USER_ID_PARAM_DESCRIPTION) - @PathVariable(USER_ID) String strUserId, - HttpServletRequest request) throws ThingsboardException { + public String getActivationLink(@Parameter(description = USER_ID_PARAM_DESCRIPTION) + @PathVariable(USER_ID) String strUserId, + HttpServletRequest request) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); - User user = checkUserId(userId, Operation.READ); - SecurityUser authUser = getCurrentUser(); - UserCredentials userCredentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), user.getId()); - if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { - String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request); - String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, - userCredentials.getActivateToken()); - return activateUrl; - } else { - throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); - } + checkUserId(userId, Operation.READ); + return getActivationLink(userId, request); } @ApiOperation(value = "Delete User (deleteUser)", @@ -411,7 +387,7 @@ public class UserController extends BaseController { public void setUserCredentialsEnabled( @Parameter(description = USER_ID_PARAM_DESCRIPTION) @PathVariable(USER_ID) String strUserId, - @Parameter(description = "Enable (\"true\") or disable (\"false\") the credentials." , schema = @Schema(defaultValue = "true")) + @Parameter(description = "Enable (\"true\") or disable (\"false\") the credentials.", schema = @Schema(defaultValue = "true")) @RequestParam(required = false, defaultValue = "true") boolean userCredentialsEnabled) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); @@ -610,6 +586,22 @@ public class UserController extends BaseController { userService.removeMobileSession(user.getTenantId(), mobileToken); } + private String getActivationLink(UserId userId, HttpServletRequest request) throws ThingsboardException { + TenantId tenantId = getTenantId(); + UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, userId); + if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { + if (userCredentials.isActivationTokenExpired()) { + userCredentials = userService.generateUserActivationToken(userCredentials); + userCredentials = userService.saveUserCredentials(tenantId, userCredentials); + log.debug("[{}][{}] Regenerated expired user activation token", tenantId, userId); + } + String baseUrl = systemSecurityService.getBaseUrl(tenantId, getCurrentUser().getCustomerId(), request); + return String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken()); + } else { + throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } + } + private void checkNotReserved(String strType, UserSettingsType type) throws ThingsboardException { if (type.isReserved()) { throw new ThingsboardException("Settings with type: " + strType + " are reserved for internal use!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java index 68595bed2e..1d5fbba859 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java @@ -56,8 +56,7 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse if (sendEmail) { UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, savedUser.getId()); String baseUrl = systemSecurityService.getBaseUrl(tenantId, customerId, request); - String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, - userCredentials.getActivateToken()); + String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken()); String email = savedUser.getEmail(); try { mailService.sendActivationEmail(activateUrl, email); diff --git a/application/src/main/java/org/thingsboard/server/service/mobile/secret/MobileAppSecretServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/mobile/secret/MobileAppSecretServiceImpl.java index bef31622ff..73496ca1a0 100644 --- a/application/src/main/java/org/thingsboard/server/service/mobile/secret/MobileAppSecretServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/mobile/secret/MobileAppSecretServiceImpl.java @@ -25,11 +25,12 @@ import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.security.model.JwtPair; import org.thingsboard.server.dao.entity.AbstractCachedService; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; -import org.thingsboard.server.service.security.system.SystemSecurityService; -import static org.thingsboard.server.service.security.system.DefaultSystemSecurityService.DEFAULT_MOBILE_SECRET_KEY_LENGTH; +import static org.thingsboard.server.dao.settings.DefaultSecuritySettingsService.DEFAULT_MOBILE_SECRET_KEY_LENGTH; + @Service @Slf4j @@ -37,12 +38,12 @@ import static org.thingsboard.server.service.security.system.DefaultSystemSecuri public class MobileAppSecretServiceImpl extends AbstractCachedService implements MobileAppSecretService { private final JwtTokenFactory tokenFactory; - private final SystemSecurityService systemSecurityService; + private final SecuritySettingsService securitySettingsService; @Override public String generateMobileAppSecret(SecurityUser securityUser) { log.trace("Executing generateSecret for user [{}]", securityUser.getId()); - Integer mobileSecretKeyLength = systemSecurityService.getSecuritySettings().getMobileSecretKeyLength(); + Integer mobileSecretKeyLength = securitySettingsService.getSecuritySettings().getMobileSecretKeyLength(); String secret = StringUtils.generateSafeToken(mobileSecretKeyLength == null ? DEFAULT_MOBILE_SECRET_KEY_LENGTH : mobileSecretKeyLength); cache.put(secret, tokenFactory.createTokenPair(securityUser)); return secret; @@ -63,4 +64,5 @@ public class MobileAppSecretServiceImpl extends AbstractCachedService 0) { if (failedLoginAttempts > securitySettings.getMaxFailedLoginAttempts() && userCredentials.isEnabled()) { lockAccount(userCredentials.getUserId(), username, securitySettings.getUserLockoutNotificationEmail(), securitySettings.getMaxFailedLoginAttempts()); @@ -153,7 +98,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService { userService.resetFailedLoginAttempts(tenantId, userCredentials.getUserId()); - SecuritySettings securitySettings = self.getSecuritySettings(); + SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); if (isPositiveInteger(securitySettings.getPasswordPolicy().getPasswordExpirationPeriodDays())) { if ((userCredentials.getCreatedTime() + TimeUnit.DAYS.toMillis(securitySettings.getPasswordPolicy().getPasswordExpirationPeriodDays())) @@ -181,7 +126,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService { if (maxVerificationFailures != null && maxVerificationFailures > 0 && failedVerificationAttempts >= maxVerificationFailures) { userService.setUserCredentialsEnabled(TenantId.SYS_TENANT_ID, userId, false); - SecuritySettings securitySettings = self.getSecuritySettings(); + SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); lockAccount(userId, securityUser.getEmail(), securitySettings.getUserLockoutNotificationEmail(), maxVerificationFailures); throw new LockedException("User account was locked due to exceeded 2FA verification attempts"); } @@ -200,7 +145,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService { @Override public void validatePassword(String password, UserCredentials userCredentials) throws DataValidationException { - SecuritySettings securitySettings = self.getSecuritySettings(); + SecuritySettings securitySettings = securitySettingsService.getSecuritySettings(); UserPasswordPolicy passwordPolicy = securitySettings.getPasswordPolicy(); validatePasswordByPolicy(password, passwordPolicy); @@ -330,4 +275,5 @@ public class DefaultSystemSecurityService implements SystemSecurityService { private static boolean isPositiveInteger(Integer val) { return val != null && val.intValue() > 0; } + } diff --git a/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java b/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java index 06e5cece81..8c1ac733ee 100644 --- a/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java +++ b/application/src/main/java/org/thingsboard/server/service/security/system/SystemSecurityService.java @@ -15,26 +15,20 @@ */ package org.thingsboard.server.service.security.system; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.core.AuthenticationException; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.security.UserCredentials; -import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; import org.thingsboard.server.common.data.security.model.mfa.PlatformTwoFaSettings; import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.service.security.model.SecurityUser; -import jakarta.servlet.http.HttpServletRequest; - public interface SystemSecurityService { - SecuritySettings getSecuritySettings(); - - SecuritySettings saveSecuritySettings(SecuritySettings securitySettings); - void validatePasswordByPolicy(String password, UserPasswordPolicy passwordPolicy); void validateUserCredentials(TenantId tenantId, UserCredentials userCredentials, String username, String password) throws AuthenticationException; @@ -48,4 +42,5 @@ public interface SystemSecurityService { void logLoginAction(User user, Object authenticationDetails, ActionType actionType, Exception e); void logLoginAction(User user, Object authenticationDetails, ActionType actionType, String provider, Exception e); + } diff --git a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java index 1cf389a93d..f3c0beab8f 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java @@ -16,20 +16,28 @@ package org.thingsboard.server.controller; import com.fasterxml.jackson.databind.JsonNode; +import org.assertj.core.data.Offset; import org.junit.After; import org.junit.Test; import org.mockito.Mockito; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.HttpHeaders; import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.StringUtils; +import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.security.Authority; +import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.dao.service.DaoSqlTest; +import org.thingsboard.server.dao.user.UserCredentialsDao; import org.thingsboard.server.service.security.auth.rest.LoginRequest; import org.thingsboard.server.service.security.model.ChangePasswordRequest; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.anyString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; @@ -39,55 +47,55 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @DaoSqlTest public class AuthControllerTest extends AbstractControllerTest { + @SpyBean + private UserCredentialsDao userCredentialsDao; + @After public void tearDown() throws Exception { loginSysAdmin(); - SecuritySettings securitySettings = doGet("/api/admin/securitySettings", SecuritySettings.class); - - securitySettings.getPasswordPolicy().setMaximumLength(72); - securitySettings.getPasswordPolicy().setForceUserToResetPasswordIfNotValid(false); - - doPost("/api/admin/securitySettings", securitySettings).andExpect(status().isOk()); + updateSecuritySettings(securitySettings -> { + securitySettings.getPasswordPolicy().setMaximumLength(72); + securitySettings.getPasswordPolicy().setForceUserToResetPasswordIfNotValid(false); + }); } @Test public void testGetUser() throws Exception { - doGet("/api/auth/user") - .andExpect(status().isUnauthorized()); - + .andExpect(status().isUnauthorized()); + loginSysAdmin(); doGet("/api/auth/user") - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.SYS_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(SYS_ADMIN_EMAIL))); - + .andExpect(status().isOk()) + .andExpect(jsonPath("$.authority", is(Authority.SYS_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(SYS_ADMIN_EMAIL))); + loginTenantAdmin(); doGet("/api/auth/user") - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.TENANT_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(TENANT_ADMIN_EMAIL))); - + .andExpect(status().isOk()) + .andExpect(jsonPath("$.authority", is(Authority.TENANT_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(TENANT_ADMIN_EMAIL))); + loginCustomerUser(); doGet("/api/auth/user") - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.CUSTOMER_USER.name()))) - .andExpect(jsonPath("$.email",is(CUSTOMER_USER_EMAIL))); + .andExpect(status().isOk()) + .andExpect(jsonPath("$.authority", is(Authority.CUSTOMER_USER.name()))) + .andExpect(jsonPath("$.email", is(CUSTOMER_USER_EMAIL))); } - + @Test public void testLoginLogout() throws Exception { loginSysAdmin(); doGet("/api/auth/user") - .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.SYS_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(SYS_ADMIN_EMAIL))); + .andExpect(status().isOk()) + .andExpect(jsonPath("$.authority", is(Authority.SYS_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(SYS_ADMIN_EMAIL))); TimeUnit.SECONDS.sleep(1); //We need to make sure that event for invalidating token was successfully processed logout(); doGet("/api/auth/user") - .andExpect(status().isUnauthorized()); + .andExpect(status().isUnauthorized()); resetTokens(); } @@ -97,14 +105,14 @@ public class AuthControllerTest extends AbstractControllerTest { loginSysAdmin(); doGet("/api/auth/user") .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.SYS_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(SYS_ADMIN_EMAIL))); + .andExpect(jsonPath("$.authority", is(Authority.SYS_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(SYS_ADMIN_EMAIL))); refreshToken(); doGet("/api/auth/user") .andExpect(status().isOk()) - .andExpect(jsonPath("$.authority",is(Authority.SYS_ADMIN.name()))) - .andExpect(jsonPath("$.email",is(SYS_ADMIN_EMAIL))); + .andExpect(jsonPath("$.authority", is(Authority.SYS_ADMIN.name()))) + .andExpect(jsonPath("$.email", is(SYS_ADMIN_EMAIL))); } @Test @@ -131,10 +139,10 @@ public class AuthControllerTest extends AbstractControllerTest { loginUser(TENANT_ADMIN_EMAIL, newPassword); loginSysAdmin(); - SecuritySettings securitySettings = doGet("/api/admin/securitySettings", SecuritySettings.class); - securitySettings.getPasswordPolicy().setMaximumLength(15); - securitySettings.getPasswordPolicy().setForceUserToResetPasswordIfNotValid(true); - doPost("/api/admin/securitySettings", securitySettings).andExpect(status().isOk()); + updateSecuritySettings(securitySettings -> { + securitySettings.getPasswordPolicy().setMaximumLength(15); + securitySettings.getPasswordPolicy().setForceUserToResetPasswordIfNotValid(true); + }); //try to login with user password that is not valid after security settings was updated doPost("/api/auth/login", new LoginRequest(TENANT_ADMIN_EMAIL, newPassword)) @@ -142,6 +150,7 @@ public class AuthControllerTest extends AbstractControllerTest { .andExpect(jsonPath("$.message", is("The entered password violates our policies. If this is your real password, please reset it."))); } + @Test public void testShouldNotResetPasswordToTooLongValue() throws Exception { loginTenantAdmin(); @@ -163,9 +172,72 @@ public class AuthControllerTest extends AbstractControllerTest { Mockito.doNothing().when(mailService).sendPasswordWasResetEmail(anyString(), anyString()); doPost("/api/noauth/resetPassword", resetPasswordRequest) - .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message", - is("Password must be no more than 72 characters in length."))); + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message", + is("Password must be no more than 72 characters in length."))); + } + + @Test + public void testPasswordResetLinkTtl() throws Exception { + loginSysAdmin(); + int ttl = 24; + updateSecuritySettings(securitySettings -> { + securitySettings.setPasswordResetTokenTtl(ttl); + }); + doPost("/api/noauth/resetPasswordByEmail", JacksonUtil.newObjectNode() + .put("email", TENANT_ADMIN_EMAIL)).andExpect(status().isOk()); + + UserCredentials userCredentials = userCredentialsDao.findByUserId(tenantId, tenantAdminUserId.getId()); + assertThat(userCredentials.getResetTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); + userCredentials.setResetTokenExpTime(System.currentTimeMillis() - 1); + userCredentialsDao.save(tenantId, userCredentials); + + doGet("/api/noauth/resetPassword?resetToken={resetToken}", this.currentResetPasswordToken) + .andExpect(status().isConflict()); + JsonNode resetPasswordRequest = JacksonUtil.newObjectNode() + .put("resetToken", this.currentResetPasswordToken) + .put("password", "wefwefe"); + doPost("/api/noauth/resetPassword", resetPasswordRequest).andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message", is("Password reset token expired"))); + } + + @Test + public void testActivationLinkTtl() throws Exception { + loginSysAdmin(); + int ttl = 24; + updateSecuritySettings(securitySettings -> { + securitySettings.setUserActivationTokenTtl(ttl); + }); + + loginTenantAdmin(); + User user = new User(); + user.setAuthority(Authority.TENANT_ADMIN); + user.setEmail("tenant-admin-2@thingsboard.org"); + user = doPost("/api/user", user, User.class); + + UserCredentials userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); + assertThat(userCredentials.getActivateTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); + String initialActivationLink = doGet("/api/user/" + user.getId() + "/activationLink", String.class); + String initialActivationToken = StringUtils.substringAfterLast(initialActivationLink, "activateToken="); + + userCredentials.setActivateTokenExpTime(System.currentTimeMillis() - 1); + userCredentialsDao.save(tenantId, userCredentials); + doGet("/api/noauth/activate?activateToken={activateToken}", initialActivationToken) + .andExpect(status().isConflict()); + doPost("/api/noauth/activate", JacksonUtil.newObjectNode() + .put("activateToken", initialActivationToken) + .put("password", "wefewe")).andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message", is("Activation token expired"))); + + String regeneratedActivationLink = doGet("/api/user/" + user.getId() + "/activationLink", String.class); + String regeneratedActivationToken = StringUtils.substringAfterLast(regeneratedActivationLink, "activateToken="); + assertThat(regeneratedActivationToken).isNotEqualTo(initialActivationLink); + userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); + assertThat(userCredentials.getActivateTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); + + doPost("/api/noauth/activate", JacksonUtil.newObjectNode() + .put("activateToken", regeneratedActivationToken) + .put("password", "wefewe")).andExpect(status().isOk()); } @Test @@ -173,4 +245,11 @@ public class AuthControllerTest extends AbstractControllerTest { doGet("/login").andExpect(status().isOk()); doGet("/home").andExpect(status().isOk()); } + + private void updateSecuritySettings(Consumer updater) throws Exception { + SecuritySettings securitySettings = doGet("/api/admin/securitySettings", SecuritySettings.class); + updater.accept(securitySettings); + doPost("/api/admin/securitySettings", securitySettings).andExpect(status().isOk()); + } + } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java index c3ecf80268..8f22812cfc 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java @@ -17,12 +17,12 @@ package org.thingsboard.server.dao.user; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.User; -import org.thingsboard.server.common.data.mobile.MobileSessionInfo; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; import org.thingsboard.server.common.data.id.UserCredentialsId; import org.thingsboard.server.common.data.id.UserId; +import org.thingsboard.server.common.data.mobile.MobileSessionInfo; import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.UserCredentials; @@ -59,6 +59,10 @@ public interface UserService extends EntityDaoService { UserCredentials requestExpiredPasswordReset(TenantId tenantId, UserCredentialsId userCredentialsId); + UserCredentials generatePasswordResetToken(UserCredentials userCredentials); + + UserCredentials generateUserActivationToken(UserCredentials userCredentials); + UserCredentials replaceUserCredentials(TenantId tenantId, UserCredentials userCredentials); void deleteUser(TenantId tenantId, User user); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java index ed036e482a..06645feec3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java @@ -16,41 +16,31 @@ package org.thingsboard.server.common.data.security; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.databind.JsonNode; +import lombok.Data; import lombok.EqualsAndHashCode; -import org.thingsboard.server.common.data.BaseData; +import lombok.ToString; +import org.thingsboard.server.common.data.BaseDataWithAdditionalInfo; import org.thingsboard.server.common.data.id.UserCredentialsId; import org.thingsboard.server.common.data.id.UserId; -import org.thingsboard.server.common.data.validation.NoXss; -import static org.thingsboard.server.common.data.BaseDataWithAdditionalInfo.getJson; -import static org.thingsboard.server.common.data.BaseDataWithAdditionalInfo.setJson; +import java.io.Serial; +@Data @EqualsAndHashCode(callSuper = true) -public class UserCredentials extends BaseData { +@ToString(callSuper = true) +public class UserCredentials extends BaseDataWithAdditionalInfo { + @Serial private static final long serialVersionUID = -2108436378880529163L; private UserId userId; private boolean enabled; private String password; private String activateToken; + private Long activateTokenExpTime; private String resetToken; + private Long resetTokenExpTime; - @NoXss - private transient JsonNode additionalInfo; - - @JsonIgnore - private byte[] additionalInfoBytes; - - public JsonNode getAdditionalInfo() { - return getJson(() -> additionalInfo, () -> additionalInfoBytes); - } - - public void setAdditionalInfo(JsonNode settings) { - setJson(settings, json -> this.additionalInfo = json, bytes -> this.additionalInfoBytes = bytes); - } - public UserCredentials() { super(); } @@ -59,75 +49,15 @@ public class UserCredentials extends BaseData { super(id); } - public UserCredentials(UserCredentials userCredentials) { - super(userCredentials); - this.userId = userCredentials.getUserId(); - this.password = userCredentials.getPassword(); - this.enabled = userCredentials.isEnabled(); - this.activateToken = userCredentials.getActivateToken(); - this.resetToken = userCredentials.getResetToken(); - setAdditionalInfo(userCredentials.getAdditionalInfo()); - } - - public UserId getUserId() { - return userId; - } - - public void setUserId(UserId userId) { - this.userId = userId; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public String getPassword() { - return password; - } - public void setPassword(String password) { - this.password = password; - } - - public String getActivateToken() { - return activateToken; - } - - public void setActivateToken(String activateToken) { - this.activateToken = activateToken; - } - - public String getResetToken() { - return resetToken; - } - - public void setResetToken(String resetToken) { - this.resetToken = resetToken; + @JsonIgnore + public boolean isActivationTokenExpired() { + return activateTokenExpTime == null || System.currentTimeMillis() > activateTokenExpTime; } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("UserCredentials [userId="); - builder.append(userId); - builder.append(", enabled="); - builder.append(enabled); - builder.append(", password="); - builder.append(password); - builder.append(", activateToken="); - builder.append(activateToken); - builder.append(", resetToken="); - builder.append(resetToken); - builder.append(", createdTime="); - builder.append(createdTime); - builder.append(", id="); - builder.append(id); - builder.append("]"); - return builder.toString(); + @JsonIgnore + public boolean isResetTokenExpired() { + return resetTokenExpTime == null || System.currentTimeMillis() > resetTokenExpTime; } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java index aa4d303440..70e1853ffd 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/model/SecuritySettings.java @@ -16,22 +16,39 @@ package org.thingsboard.server.common.data.security.model; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import lombok.Data; +import java.io.Serial; import java.io.Serializable; @Schema @Data public class SecuritySettings implements Serializable { + @Serial private static final long serialVersionUID = -1307613974597312465L; - @Schema(description = "The user password policy object." ) + @Schema(description = "The user password policy object.") private UserPasswordPolicy passwordPolicy; - @Schema(description = "Maximum number of failed login attempts allowed before user account is locked." ) + + @Schema(description = "Maximum number of failed login attempts allowed before user account is locked.") private Integer maxFailedLoginAttempts; - @Schema(description = "Email to use for notifications about locked users." ) + + @Schema(description = "Email to use for notifications about locked users.") private String userLockoutNotificationEmail; - @Schema(description = "Mobile secret key length" ) + + @Schema(description = "Mobile secret key length") private Integer mobileSecretKeyLength; + + @NotNull @Min(1) @Max(24) + @Schema(description = "TTL in hours for user activation link", minimum = "1", maximum = "24", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer userActivationTokenTtl; + + @NotNull @Min(1) @Max(24) + @Schema(description = "TTL in hours for password reset link", minimum = "1", maximum = "24", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer passwordResetTokenTtl; + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index fb77ad6987..4194112bb9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -77,7 +77,9 @@ public class ModelConstants { public static final String USER_CREDENTIALS_ENABLED_PROPERTY = "enabled"; public static final String USER_CREDENTIALS_PASSWORD_PROPERTY = "password"; //NOSONAR, the constant used to identify password column name (not password value itself) public static final String USER_CREDENTIALS_ACTIVATE_TOKEN_PROPERTY = "activate_token"; + public static final String USER_CREDENTIALS_ACTIVATE_TOKEN_EXP_TIME_PROPERTY = "activate_token_exp_time"; public static final String USER_CREDENTIALS_RESET_TOKEN_PROPERTY = "reset_token"; + public static final String USER_CREDENTIALS_RESET_TOKEN_EXP_TIME_PROPERTY = "reset_token_exp_time"; public static final String USER_CREDENTIALS_ADDITIONAL_PROPERTY = "additional_info"; /** diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java index e7907921bf..edd1536a04 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserCredentialsEntity.java @@ -16,7 +16,10 @@ package org.thingsboard.server.dao.model.sql; import com.fasterxml.jackson.databind.JsonNode; +import jakarta.persistence.Column; import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import lombok.Data; import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.id.UserCredentialsId; @@ -25,10 +28,6 @@ import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; import org.thingsboard.server.dao.util.mapping.JsonConverter; import java.util.UUID; @@ -51,9 +50,15 @@ public final class UserCredentialsEntity extends BaseSqlEntity @Column(name = ModelConstants.USER_CREDENTIALS_ACTIVATE_TOKEN_PROPERTY, unique = true) private String activateToken; + @Column(name = ModelConstants.USER_CREDENTIALS_ACTIVATE_TOKEN_EXP_TIME_PROPERTY) + private Long activateTokenExpTime; + @Column(name = ModelConstants.USER_CREDENTIALS_RESET_TOKEN_PROPERTY, unique = true) private String resetToken; + @Column(name = ModelConstants.USER_CREDENTIALS_RESET_TOKEN_EXP_TIME_PROPERTY) + private Long resetTokenExpTime; + @Convert(converter = JsonConverter.class) @Column(name = ModelConstants.USER_CREDENTIALS_ADDITIONAL_PROPERTY) private JsonNode additionalInfo; @@ -73,7 +78,9 @@ public final class UserCredentialsEntity extends BaseSqlEntity this.enabled = userCredentials.isEnabled(); this.password = userCredentials.getPassword(); this.activateToken = userCredentials.getActivateToken(); + this.activateTokenExpTime = userCredentials.getActivateTokenExpTime(); this.resetToken = userCredentials.getResetToken(); + this.resetTokenExpTime = userCredentials.getResetTokenExpTime(); this.additionalInfo = userCredentials.getAdditionalInfo(); } @@ -87,7 +94,9 @@ public final class UserCredentialsEntity extends BaseSqlEntity userCredentials.setEnabled(enabled); userCredentials.setPassword(password); userCredentials.setActivateToken(activateToken); + userCredentials.setActivateTokenExpTime(activateTokenExpTime); userCredentials.setResetToken(resetToken); + userCredentials.setResetTokenExpTime(resetTokenExpTime); userCredentials.setAdditionalInfo(additionalInfo); return userCredentials; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/settings/DefaultSecuritySettingsService.java b/dao/src/main/java/org/thingsboard/server/dao/settings/DefaultSecuritySettingsService.java new file mode 100644 index 0000000000..18c2f68c0a --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/settings/DefaultSecuritySettingsService.java @@ -0,0 +1,81 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.settings; + +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.thingsboard.common.util.JacksonUtil; +import org.thingsboard.server.common.data.AdminSettings; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.security.model.SecuritySettings; +import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; +import org.thingsboard.server.dao.service.ConstraintValidator; + +import static org.thingsboard.server.common.data.CacheConstants.SECURITY_SETTINGS_CACHE; + +@Service +@RequiredArgsConstructor +public class DefaultSecuritySettingsService implements SecuritySettingsService { + + private final AdminSettingsService adminSettingsService; + + public static final int DEFAULT_MOBILE_SECRET_KEY_LENGTH = 64; + + @Cacheable(cacheNames = SECURITY_SETTINGS_CACHE, key = "'securitySettings'") + @Override + public SecuritySettings getSecuritySettings() { + AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "securitySettings"); + SecuritySettings securitySettings; + if (adminSettings != null) { + try { + securitySettings = JacksonUtil.convertValue(adminSettings.getJsonValue(), SecuritySettings.class); + } catch (Exception e) { + throw new RuntimeException("Failed to load security settings!", e); + } + } else { + securitySettings = new SecuritySettings(); + securitySettings.setPasswordPolicy(new UserPasswordPolicy()); + securitySettings.getPasswordPolicy().setMinimumLength(6); + securitySettings.getPasswordPolicy().setMaximumLength(72); + securitySettings.setMobileSecretKeyLength(DEFAULT_MOBILE_SECRET_KEY_LENGTH); + securitySettings.setPasswordResetTokenTtl(24); + securitySettings.setUserActivationTokenTtl(24); + } + return securitySettings; + } + + @CacheEvict(cacheNames = SECURITY_SETTINGS_CACHE, key = "'securitySettings'") + @Override + public SecuritySettings saveSecuritySettings(SecuritySettings securitySettings) { + ConstraintValidator.validateFields(securitySettings); + AdminSettings adminSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "securitySettings"); + if (adminSettings == null) { + adminSettings = new AdminSettings(); + adminSettings.setTenantId(TenantId.SYS_TENANT_ID); + adminSettings.setKey("securitySettings"); + } + adminSettings.setJsonValue(JacksonUtil.valueToTree(securitySettings)); + AdminSettings savedAdminSettings = adminSettingsService.saveAdminSettings(TenantId.SYS_TENANT_ID, adminSettings); + try { + return JacksonUtil.convertValue(savedAdminSettings.getJsonValue(), SecuritySettings.class); + } catch (Exception e) { + throw new RuntimeException("Failed to load security settings!", e); + } + } + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/settings/SecuritySettingsService.java b/dao/src/main/java/org/thingsboard/server/dao/settings/SecuritySettingsService.java new file mode 100644 index 0000000000..8b9e3bfeee --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/settings/SecuritySettingsService.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.dao.settings; + +import org.thingsboard.server.common.data.security.model.SecuritySettings; + +public interface SecuritySettingsService { + + SecuritySettings getSecuritySettings(); + + SecuritySettings saveSecuritySettings(SecuritySettings securitySettings); + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java index 34602d81b3..0dbc8af201 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java @@ -60,6 +60,7 @@ import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; +import org.thingsboard.server.dao.settings.SecuritySettingsService; import org.thingsboard.server.dao.sql.JpaExecutorService; import java.util.ArrayList; @@ -69,6 +70,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.TimeUnit; import static org.thingsboard.server.common.data.StringUtils.generateSafeToken; import static org.thingsboard.server.dao.service.Validator.validateId; @@ -99,6 +101,7 @@ public class UserServiceImpl extends AbstractCachedEntityService userValidator; private final DataValidator userCredentialsValidator; private final ApplicationEventPublisher eventPublisher; @@ -175,9 +178,9 @@ public class UserServiceImpl extends AbstractCachedEntityService Date: Wed, 24 Jul 2024 13:23:18 +0300 Subject: [PATCH 08/80] UI for password reset and user activation links TTL (Security settings) --- .../admin/security-settings.component.html | 38 +++++++++++++++++++ .../admin/security-settings.component.ts | 3 ++ .../src/app/shared/models/settings.models.ts | 5 +++ .../assets/locale/locale.constant-en_US.json | 6 +++ 4 files changed, 52 insertions(+) diff --git a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html index 3d399d01a1..0b9df7c5ae 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.html @@ -46,6 +46,44 @@ + + admin.user-activation-token-ttl + + + {{ 'admin.user-activation-token-ttl-range' | translate }} + + + {{ 'admin.user-activation-token-ttl-range' | translate }} + + + + admin.password-reset-token-ttl + + + {{ 'admin.password-reset-token-ttl-range' | translate }} + + + {{ 'admin.password-reset-token-ttl-range' | translate }} + + + + admin.mobile-secret-key-length + + + {{ 'admin.mobile-secret-key-length-range' | translate }} + +
diff --git a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts index c7ac489753..712e2bb358 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/security-settings.component.ts @@ -75,6 +75,9 @@ export class SecuritySettingsComponent extends PageComponent implements HasConfi this.securitySettingsFormGroup = this.fb.group({ maxFailedLoginAttempts: [null, [Validators.min(0)]], userLockoutNotificationEmail: ['', []], + userActivationTokenTtl: [24, [Validators.required, Validators.min(1), Validators.max(24)]], + passwordResetTokenTtl: [24, [Validators.required, Validators.min(1), Validators.max(24)]], + mobileSecretKeyLength: [null, [Validators.min(1)]], passwordPolicy: this.fb.group( { minimumLength: [null, [Validators.required, Validators.min(6), Validators.max(50)]], diff --git a/ui-ngx/src/app/shared/models/settings.models.ts b/ui-ngx/src/app/shared/models/settings.models.ts index 113bc1a789..e0a31e4eea 100644 --- a/ui-ngx/src/app/shared/models/settings.models.ts +++ b/ui-ngx/src/app/shared/models/settings.models.ts @@ -111,6 +111,11 @@ export interface UserPasswordPolicy { export interface SecuritySettings { passwordPolicy: UserPasswordPolicy; + maxFailedLoginAttempts: number; + userLockoutNotificationEmail: string; + mobileSecretKeyLength: number; + userActivationTokenTtl: number; + passwordResetTokenTtl: number; } export interface JwtSettings { diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 33c8d25652..3e56a104fb 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -205,6 +205,12 @@ "max-failed-login-attempts": "Maximum number of failed login attempts, before account is locked", "minimum-max-failed-login-attempts-range": "Maximum number of failed login attempts can't be negative", "user-lockout-notification-email": "In case user account lockout, send notification to email", + "user-activation-token-ttl": "User activation link TTL in hours", + "user-activation-token-ttl-range": "User activation link TTL must be in range from 1 to 24 hours", + "password-reset-token-ttl": "Password reset link TTL in hours", + "password-reset-token-ttl-range": "Password reset link TTL must be in range from 1 to 24 hours", + "mobile-secret-key-length": "Mobile secret key length", + "mobile-secret-key-length-range": "Mobile secret key length must be positive", "domain-name": "Domain name", "domain-name-unique": "Domain name and protocol need to unique.", "domain-name-max-length": "Domain name should be less than 256", From a246032e543c99983179990f409aef8e4a0955b2 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 24 Jul 2024 13:41:25 +0300 Subject: [PATCH 09/80] Clear security settings cache on upgrade --- .../org/thingsboard/server/controller/AuthController.java | 6 +----- .../service/install/update/DefaultCacheCleanupService.java | 5 +++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index 86301cfb6a..5d10648be7 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -31,8 +31,6 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.cache.limits.RateLimitService; @@ -86,8 +84,7 @@ public class AuthController extends BaseController { notes = "Get the information about the User which credentials are used to perform this REST API call.") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @GetMapping(value = "/auth/user") - public @ResponseBody - User getUser() throws ThingsboardException { + public User getUser() throws ThingsboardException { SecurityUser securityUser = getCurrentUser(); return userService.findUserById(securityUser.getTenantId(), securityUser.getId()); } @@ -96,7 +93,6 @@ public class AuthController extends BaseController { notes = "Special API call to record the 'logout' of the user to the Audit Logs. Since platform uses [JWT](https://jwt.io/), the actual logout is the procedure of clearing the [JWT](https://jwt.io/) token on the client side. ") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PostMapping(value = "/auth/logout") - @ResponseStatus(value = HttpStatus.OK) public void logout(HttpServletRequest request) throws ThingsboardException { logLogoutAction(request); } diff --git a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java index 7fd92bc5c6..f5b206d367 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/update/DefaultCacheCleanupService.java @@ -61,6 +61,10 @@ public class DefaultCacheCleanupService implements CacheCleanupService { log.info("Clearing cache to upgrade from version 3.6.4 to 3.7.0"); clearAll(); break; + case "3.7.0": + log.info("Clearing cache to upgrade from version 3.7.0 to 3.7.1"); + clearCacheByName(SECURITY_SETTINGS_CACHE); + break; default: //Do nothing, since cache cleanup is optional. } @@ -88,4 +92,5 @@ public class DefaultCacheCleanupService implements CacheCleanupService { } cacheManager.getCacheNames().forEach(this::clearCacheByName); } + } From 478d20aec73cdebdf8e9fcc5de05fdd8894635ed Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Thu, 25 Jul 2024 11:49:10 +0300 Subject: [PATCH 10/80] Status '410 Gone' when token is expired --- .../server/controller/AuthController.java | 74 +++++++++---------- .../server/controller/BaseController.java | 6 ++ .../server/controller/ImageController.java | 2 +- .../MobileApplicationController.java | 3 +- .../server/controller/AuthControllerTest.java | 4 +- 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index 5d10648be7..aa194d688e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -21,7 +21,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; @@ -132,28 +131,28 @@ public class AuthController extends BaseController { @ApiOperation(value = "Check Activate User Token (checkActivateToken)", notes = "Checks the activation token and forwards user to 'Create Password' page. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Create Password' page and same 'activateToken' specified in the URL parameters. " + - "If token is not valid, returns '409 Conflict'.") + "If token is not valid, returns '409 Conflict'. " + + "If token is expired, returns '410 Gone'.") @GetMapping(value = "/noauth/activate", params = {"activateToken"}) - public ResponseEntity checkActivateToken( + public ResponseEntity checkActivateToken( @Parameter(description = "The activate token string.") @RequestParam(value = "activateToken") String activateToken) { - HttpHeaders headers = new HttpHeaders(); - HttpStatus responseStatus; UserCredentials userCredentials = userService.findUserCredentialsByActivateToken(TenantId.SYS_TENANT_ID, activateToken); - if (userCredentials != null && !userCredentials.isActivationTokenExpired()) { - String createURI = "/login/createPassword"; - try { - URI location = new URI(createURI + "?activateToken=" + activateToken); - headers.setLocation(location); - responseStatus = HttpStatus.SEE_OTHER; - } catch (URISyntaxException e) { - log.error("Unable to create URI with address [{}]", createURI); - responseStatus = HttpStatus.BAD_REQUEST; - } - } else { - responseStatus = HttpStatus.CONFLICT; + if (userCredentials == null) { + return response(HttpStatus.CONFLICT); + } else if (userCredentials.isActivationTokenExpired()) { + return response(HttpStatus.GONE); + } + + String createURI = "/login/createPassword"; + try { + URI location = new URI(createURI + "?activateToken=" + activateToken); + return ResponseEntity.status(HttpStatus.SEE_OTHER) + .location(location).build(); + } catch (URISyntaxException e) { + log.error("Unable to create URI with address [{}]", createURI); + return response(HttpStatus.BAD_REQUEST); } - return new ResponseEntity<>(headers, responseStatus); } @ApiOperation(value = "Request reset password email (requestResetPasswordByEmail)", @@ -181,32 +180,31 @@ public class AuthController extends BaseController { @ApiOperation(value = "Check password reset token (checkResetToken)", notes = "Checks the password reset token and forwards user to 'Reset Password' page. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Reset Password' page and same 'resetToken' specified in the URL parameters. " + - "If token is not valid, returns '409 Conflict'.") + "If token is not valid, returns '409 Conflict'. " + + "If token is expired, returns '410 Gone'.") @GetMapping(value = "/noauth/resetPassword", params = {"resetToken"}) - public ResponseEntity checkResetToken( + public ResponseEntity checkResetToken( @Parameter(description = "The reset token string.") @RequestParam(value = "resetToken") String resetToken) { - HttpHeaders headers = new HttpHeaders(); - HttpStatus responseStatus; - String resetURI = "/login/resetPassword"; UserCredentials userCredentials = userService.findUserCredentialsByResetToken(TenantId.SYS_TENANT_ID, resetToken); + if (userCredentials == null) { + return response(HttpStatus.CONFLICT); + } else if (userCredentials.isResetTokenExpired()) { + return response(HttpStatus.GONE); + } + if (!rateLimitService.checkRateLimit(LimitedApi.PASSWORD_RESET, userCredentials.getUserId(), defaultLimitsConfiguration)) { + return response(HttpStatus.TOO_MANY_REQUESTS); + } - if (userCredentials != null && !userCredentials.isResetTokenExpired()) { - if (!rateLimitService.checkRateLimit(LimitedApi.PASSWORD_RESET, userCredentials.getUserId(), defaultLimitsConfiguration)) { - return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).build(); - } - try { - URI location = new URI(resetURI + "?resetToken=" + resetToken); - headers.setLocation(location); - responseStatus = HttpStatus.SEE_OTHER; - } catch (URISyntaxException e) { - log.error("Unable to create URI with address [{}]", resetURI); - responseStatus = HttpStatus.BAD_REQUEST; - } - } else { - responseStatus = HttpStatus.CONFLICT; + String resetURI = "/login/resetPassword"; + try { + URI location = new URI(resetURI + "?resetToken=" + resetToken); + return ResponseEntity.status(HttpStatus.SEE_OTHER) + .location(location).build(); + } catch (URISyntaxException e) { + log.error("Unable to create URI with address [{}]", resetURI); + return response(HttpStatus.BAD_REQUEST); } - return new ResponseEntity<>(headers, responseStatus); } @ApiOperation(value = "Activate User", diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index da956d4fa5..52772bbf2b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -27,7 +27,9 @@ import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.DataAccessException; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.MethodArgumentNotValidException; @@ -867,4 +869,8 @@ public abstract class BaseController { } } + protected ResponseEntity response(HttpStatus status) { + return ResponseEntity.status(status).build(); + } + } diff --git a/application/src/main/java/org/thingsboard/server/controller/ImageController.java b/application/src/main/java/org/thingsboard/server/controller/ImageController.java index e8e7ca1d8f..0228739399 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ImageController.java +++ b/application/src/main/java/org/thingsboard/server/controller/ImageController.java @@ -290,7 +290,7 @@ public class ImageController extends BaseController { if (StringUtils.isNotEmpty(etag)) { etag = StringUtils.remove(etag, '\"'); // etag is wrapped in double quotes due to HTTP specification if (etag.equals(tbImageService.getETag(cacheKey))) { - return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build(); + return response(HttpStatus.NOT_MODIFIED); } } diff --git a/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java b/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java index ca8b11ee80..11f017b85f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java +++ b/application/src/main/java/org/thingsboard/server/controller/MobileApplicationController.java @@ -183,8 +183,7 @@ public class MobileApplicationController extends BaseController { .header("Location", appStoreLink) .build(); } else { - return ResponseEntity.status(HttpStatus.NOT_FOUND) - .build(); + return response(HttpStatus.NOT_FOUND); } } diff --git a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java index f3c0beab8f..dba5a84e1b 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java @@ -193,7 +193,7 @@ public class AuthControllerTest extends AbstractControllerTest { userCredentialsDao.save(tenantId, userCredentials); doGet("/api/noauth/resetPassword?resetToken={resetToken}", this.currentResetPasswordToken) - .andExpect(status().isConflict()); + .andExpect(status().isGone()); JsonNode resetPasswordRequest = JacksonUtil.newObjectNode() .put("resetToken", this.currentResetPasswordToken) .put("password", "wefwefe"); @@ -223,7 +223,7 @@ public class AuthControllerTest extends AbstractControllerTest { userCredentials.setActivateTokenExpTime(System.currentTimeMillis() - 1); userCredentialsDao.save(tenantId, userCredentials); doGet("/api/noauth/activate?activateToken={activateToken}", initialActivationToken) - .andExpect(status().isConflict()); + .andExpect(status().isGone()); doPost("/api/noauth/activate", JacksonUtil.newObjectNode() .put("activateToken", initialActivationToken) .put("password", "wefewe")).andExpect(status().isBadRequest()) From 864ba221eacfb300382e12fcc9be7e16a1cab6de Mon Sep 17 00:00:00 2001 From: d2eight Date: Mon, 29 Jul 2024 19:38:13 +0300 Subject: [PATCH 11/80] Card-padding for some widgets --- .../value-card-basic-config.component.html | 6 ++ .../value-card-basic-config.component.ts | 2 + .../status-widget-basic-config.component.html | 6 ++ .../status-widget-basic-config.component.ts | 5 +- .../single-switch-basic-config.component.html | 6 ++ .../single-switch-basic-config.component.ts | 2 + ...peed-direction-basic-config.component.html | 6 ++ ...-speed-direction-basic-config.component.ts | 2 + .../cards/value-card-widget.component.html | 56 +++++++++---------- .../lib/cards/value-card-widget.component.ts | 17 +++++- .../lib/cards/value-card-widget.models.ts | 4 +- .../indicator/status-widget.component.html | 2 +- .../indicator/status-widget.component.scss | 1 - .../lib/indicator/status-widget.component.ts | 16 +++++- .../lib/indicator/status-widget.models.ts | 4 +- .../rpc/single-switch-widget.component.html | 2 +- .../lib/rpc/single-switch-widget.component.ts | 16 +++++- .../lib/rpc/single-switch-widget.models.ts | 4 +- .../value-card-widget-settings.component.html | 6 ++ .../value-card-widget-settings.component.ts | 3 +- ...ngle-switch-widget-settings.component.html | 6 ++ ...single-switch-widget-settings.component.ts | 3 +- .../status-widget-settings.component.html | 6 ++ .../status-widget-settings.component.ts | 3 +- ...d-direction-widget-settings.component.html | 6 ++ ...eed-direction-widget-settings.component.ts | 3 +- ...wind-speed-direction-widget.component.html | 2 +- .../wind-speed-direction-widget.component.ts | 2 + .../wind-speed-direction-widget.models.ts | 4 +- 29 files changed, 151 insertions(+), 50 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html index 44e288d2e0..c1f0d7e635 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.html @@ -126,6 +126,12 @@ +
+
{{ 'widget-config.card-padding' | translate }}
+ + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts index 0bffd39ce4..5f14b7569e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/cards/value-card-basic-config.component.ts @@ -144,6 +144,7 @@ export class ValueCardBasicConfigComponent extends BasicWidgetConfigComponent { cardButtons: [this.getCardButtons(configData.config), []], borderRadius: [configData.config.borderRadius, []], + padding: [settings.padding, []], actions: [configData.config.actions || {}, []] }); @@ -183,6 +184,7 @@ export class ValueCardBasicConfigComponent extends BasicWidgetConfigComponent { this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.widgetConfig.config.borderRadius = config.borderRadius; + this.widgetConfig.config.settings.padding = config.padding; this.widgetConfig.config.actions = config.actions; return this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.html index 57eb184009..2370d5bdbb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.html @@ -94,6 +94,12 @@ +
+
{{ 'widget-config.card-padding' | translate }}
+ + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts index d2110026f6..c54df3321c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts @@ -29,7 +29,7 @@ import { statusWidgetLayoutImages, statusWidgetLayouts, statusWidgetLayoutTranslations, - StatusWidgetSettings + StatusWidgetSettings, StatusWidgetStateSettings } from '@home/components/widget/lib/indicator/status-widget.models'; @Component({ @@ -66,6 +66,7 @@ export class StatusWidgetBasicConfigComponent extends BasicWidgetConfigComponent protected onConfigSet(configData: WidgetConfigComponentData) { const settings: StatusWidgetSettings = {...statusWidgetDefaultSettings, ...(configData.config.settings || {})}; + this.statusWidgetConfigForm = this.fb.group({ targetDevice: [configData.config.targetDevice, []], @@ -79,6 +80,7 @@ export class StatusWidgetBasicConfigComponent extends BasicWidgetConfigComponent cardButtons: [this.getCardButtons(configData.config), []], borderRadius: [configData.config.borderRadius, []], + padding: [settings.padding, []], actions: [configData.config.actions || {}, []] }); @@ -99,6 +101,7 @@ export class StatusWidgetBasicConfigComponent extends BasicWidgetConfigComponent this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.widgetConfig.config.borderRadius = config.borderRadius; + this.widgetConfig.config.settings.padding = config.padding; this.widgetConfig.config.actions = config.actions; return this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.html index c6ac3abb45..1009057b19 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.html @@ -211,6 +211,12 @@ +
+
{{ 'widget-config.card-padding' | translate }}
+ + + +
widget-config.show-card-buttons
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts index 75c93bc852..dfdc9e8eb0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/rpc/single-switch-basic-config.component.ts @@ -108,6 +108,7 @@ export class SingleSwitchBasicConfigComponent extends BasicWidgetConfigComponent cardButtons: [this.getCardButtons(configData.config), []], borderRadius: [configData.config.borderRadius, []], + padding: [settings.padding, []], actions: [configData.config.actions || {}, []] }); @@ -159,6 +160,7 @@ export class SingleSwitchBasicConfigComponent extends BasicWidgetConfigComponent this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.widgetConfig.config.borderRadius = config.borderRadius; + this.widgetConfig.config.settings.padding = config.padding; this.widgetConfig.config.actions = config.actions; return this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.html index 7854a9f3b3..0dd9a2ebd9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.html @@ -208,6 +208,12 @@
+
+
{{ 'widget-config.card-padding' | translate }}
+ + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts index fca3bd2502..08e7003b65 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/weather/wind-speed-direction-basic-config.component.ts @@ -147,6 +147,7 @@ export class WindSpeedDirectionBasicConfigComponent extends BasicWidgetConfigCom cardButtons: [this.getCardButtons(configData.config), []], borderRadius: [configData.config.borderRadius, []], + padding: [settings.padding, []], actions: [configData.config.actions || {}, []] }); @@ -198,6 +199,7 @@ export class WindSpeedDirectionBasicConfigComponent extends BasicWidgetConfigCom this.setCardButtons(config.cardButtons, this.widgetConfig.config); this.widgetConfig.config.borderRadius = config.borderRadius; + this.widgetConfig.config.settings.padding = config.padding; this.widgetConfig.config.actions = config.actions; return this.widgetConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html index 72598a4cdf..3d8ebd76b8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html @@ -15,41 +15,41 @@ limitations under the License. --> -
+
- - - - - - - - - - - - -
+ + + + + + + + + + + +
+ + +
+ +
+ -
- -
- - - - - - -
- -
-
+ + + + +
+ +
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts index ed361c1e76..440c2d4056 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts @@ -37,7 +37,7 @@ import { getLabel, getSingleTsValue, iconStyle, - overlayStyle, + overlayStyle, resolveCssSize, textStyle } from '@shared/models/widget-settings.models'; import { valueCardDefaultSettings, ValueCardLayout, ValueCardWidgetSettings } from './value-card-widget.models'; @@ -96,6 +96,7 @@ export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestro backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; + padding: string; private panelResize$: ResizeObserver; @@ -139,6 +140,7 @@ export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestro this.labelStyle = textStyle(this.settings.labelFont); this.labelColor = ColorProcessor.fromSettings(this.settings.labelColor); this.valueStyle = textStyle(this.settings.valueFont); + console.log(this.valueStyle); this.valueColor = ColorProcessor.fromSettings(this.settings.valueColor); this.showDate = this.settings.showDate; @@ -148,6 +150,7 @@ export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestro this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); + this.padding = this.settings.background.overlay.enabled ? undefined : this.settings.padding; } public ngAfterViewInit() { @@ -199,8 +202,16 @@ export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestro } private onResize() { - const panelWidth = this.valueCardPanel.nativeElement.getBoundingClientRect().width - squareLayoutPadding; - const panelHeight = this.valueCardPanel.nativeElement.getBoundingClientRect().height - (this.horizontal ? 0 : squareLayoutPadding); + const paddingLeft = getComputedStyle(this.valueCardPanel.nativeElement).paddingLeft; + const paddingRight = getComputedStyle(this.valueCardPanel.nativeElement).paddingRight; + const paddingTop = getComputedStyle(this.valueCardPanel.nativeElement).paddingTop; + const paddingBottom = getComputedStyle(this.valueCardPanel.nativeElement).paddingBottom; + const pLeft = resolveCssSize(paddingLeft)[0]; + const pRight = resolveCssSize(paddingRight)[0]; + const pTop = resolveCssSize(paddingTop)[0]; + const pBottom = resolveCssSize(paddingBottom)[0]; + const panelWidth = this.valueCardPanel.nativeElement.getBoundingClientRect().width - (pLeft + pRight); + const panelHeight = this.valueCardPanel.nativeElement.getBoundingClientRect().height - (pTop + pBottom); let scale: number; if (!this.horizontal) { const size = Math.min(panelWidth, panelHeight); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts index df5fc78e9a..7b46ccba4d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts @@ -80,6 +80,7 @@ export interface ValueCardWidgetSettings { dateFont: Font; dateColor: ColorSettings; background: BackgroundSettings; + padding: string; } export const valueCardDefaultSettings = (horizontal: boolean): ValueCardWidgetSettings => ({ @@ -128,5 +129,6 @@ export const valueCardDefaultSettings = (horizontal: boolean): ValueCardWidgetSe color: 'rgba(255,255,255,0.72)', blur: 3 } - } + }, + padding: '12px' }); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html index 391ade6228..4a4ff409fd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss index 8dcefddd2a..a2e32fcfcc 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss @@ -38,7 +38,6 @@ .tb-status-widget-content { width: 100%; height: 100%; - padding: 16px; position: relative; display: flex; flex-direction: column; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts index 5b59b0210f..3f85917897 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts @@ -35,7 +35,7 @@ import { backgroundStyle, ComponentStyle, iconStyle, - overlayStyle, + overlayStyle, resolveCssSize, textStyle } from '@shared/models/widget-settings.models'; import { ResizeObserver } from '@juggle/resize-observer'; @@ -65,6 +65,7 @@ export class StatusWidgetComponent extends backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; + padding: string; overlayInset = '12px'; borderRadius = ''; @@ -191,8 +192,16 @@ export class StatusWidgetComponent extends } private onResize() { - const panelWidth = this.statusWidgetPanel.nativeElement.getBoundingClientRect().width; - const panelHeight = this.statusWidgetPanel.nativeElement.getBoundingClientRect().height; + const paddingLeft = getComputedStyle(this.statusWidgetPanel.nativeElement).paddingLeft; + const paddingRight = getComputedStyle(this.statusWidgetPanel.nativeElement).paddingRight; + const paddingTop = getComputedStyle(this.statusWidgetPanel.nativeElement).paddingTop; + const paddingBottom = getComputedStyle(this.statusWidgetPanel.nativeElement).paddingBottom; + const pLeft = resolveCssSize(paddingLeft)[0]; + const pRight = resolveCssSize(paddingRight)[0]; + const pTop = resolveCssSize(paddingTop)[0]; + const pBottom = resolveCssSize(paddingBottom)[0]; + const panelWidth = this.statusWidgetPanel.nativeElement.getBoundingClientRect().width - (pLeft + pRight); + const panelHeight = this.statusWidgetPanel.nativeElement.getBoundingClientRect().height - (pTop + pBottom); const targetSize = Math.min(panelWidth, panelHeight); const scale = targetSize / initialStatusWidgetSize; const width = initialStatusWidgetSize; @@ -220,6 +229,7 @@ export class StatusWidgetComponent extends this.showLabel = stateSettings.showLabel && this.layout !== StatusWidgetLayout.icon; this.showStatus = stateSettings.showStatus && this.layout !== StatusWidgetLayout.icon; this.icon = stateSettings.icon; + this.padding = stateSettings.background.overlay.enabled ? undefined : this.settings.padding; const primaryColor = disabled ? stateSettings.primaryColorDisabled : stateSettings.primaryColor; const secondaryColor = disabled ? stateSettings.secondaryColorDisabled : stateSettings.secondaryColor; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts index 2ef999c6f2..8da94a3739 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts @@ -65,6 +65,7 @@ export interface StatusWidgetSettings { layout: StatusWidgetLayout; onState: StatusWidgetStateSettings; offState: StatusWidgetStateSettings; + padding: string } export const statusWidgetDefaultSettings: StatusWidgetSettings = { @@ -200,5 +201,6 @@ export const statusWidgetDefaultSettings: StatusWidgetSettings = { blur: 3 } } - } + }, + padding: '12px' }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html index fd9aaca4a6..a8dde3ed4c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts index 2c15634893..5bfede43f2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts @@ -35,7 +35,7 @@ import { backgroundStyle, ComponentStyle, iconStyle, - overlayStyle, + overlayStyle, resolveCssSize, textStyle } from '@shared/models/widget-settings.models'; import { Observable } from 'rxjs'; @@ -74,6 +74,7 @@ export class SingleSwitchWidgetComponent extends backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; + padding: string; overlayInset = '12px'; value = false; @@ -123,6 +124,7 @@ export class SingleSwitchWidgetComponent extends this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); + this.padding = this.settings.background.overlay.enabled ? undefined : this.settings.padding; this.layout = this.settings.layout; @@ -234,8 +236,16 @@ export class SingleSwitchWidgetComponent extends const height = this.singleSwitchPanel.nativeElement.getBoundingClientRect().height; const switchScale = height / initialSwitchHeight; const paddingScale = Math.min(switchScale, 1); - const panelWidth = this.singleSwitchPanel.nativeElement.getBoundingClientRect().width - (horizontalLayoutPadding * paddingScale); - const panelHeight = this.singleSwitchPanel.nativeElement.getBoundingClientRect().height - (verticalLayoutPadding * paddingScale); + const paddingLeft = getComputedStyle(this.singleSwitchPanel.nativeElement).paddingLeft; + const paddingRight = getComputedStyle(this.singleSwitchPanel.nativeElement).paddingRight; + const paddingTop = getComputedStyle(this.singleSwitchPanel.nativeElement).paddingTop; + const paddingBottom = getComputedStyle(this.singleSwitchPanel.nativeElement).paddingBottom; + const pLeft = resolveCssSize(paddingLeft)[0]; + const pRight = resolveCssSize(paddingRight)[0]; + const pTop = resolveCssSize(paddingTop)[0]; + const pBottom = resolveCssSize(paddingBottom)[0]; + const panelWidth = this.singleSwitchPanel.nativeElement.getBoundingClientRect().width - (pLeft + pRight); + const panelHeight = this.singleSwitchPanel.nativeElement.getBoundingClientRect().height - (pTop + pBottom); this.renderer.setStyle(this.singleSwitchContent.nativeElement, 'transform', `scale(1)`); this.renderer.setStyle(this.singleSwitchContent.nativeElement, 'width', 'auto'); let contentWidth = this.singleSwitchToggleRow.nativeElement.getBoundingClientRect().width; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts index 94586c31de..2fe9ab0d96 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts @@ -80,6 +80,7 @@ export interface SingleSwitchWidgetSettings { offLabelFont: Font; offLabelColor: string; background: BackgroundSettings; + padding: string; } export const singleSwitchDefaultSettings: SingleSwitchWidgetSettings = { @@ -217,5 +218,6 @@ export const singleSwitchDefaultSettings: SingleSwitchWidgetSettings = { color: 'rgba(255,255,255,0.72)', blur: 3 } - } + }, + padding: '12px' }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.html index 76f46862a6..5077c93d8e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.html @@ -93,5 +93,11 @@
+
+
{{ 'widget-config.card-padding' | translate }}
+ + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts index 9693ca22d4..be7794802c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/value-card-widget-settings.component.ts @@ -110,7 +110,8 @@ export class ValueCardWidgetSettingsComponent extends WidgetSettingsComponent { dateFont: [settings.dateFont, []], dateColor: [settings.dateColor, []], - background: [settings.background, []] + background: [settings.background, []], + padding: [settings.padding, []] }); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.html index 9208efd68a..e08b40882b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.html @@ -123,6 +123,12 @@
+
+
{{ 'widget-config.card-padding' | translate }}
+ + + +
widgets.single-switch.switch
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts index a1a3e951f2..a4a76e5294 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/control/single-switch-widget-settings.component.ts @@ -102,7 +102,8 @@ export class SingleSwitchWidgetSettingsComponent extends WidgetSettingsComponent offLabelFont: [settings.offLabelFont, []], offLabelColor: [settings.offLabelColor, []], - background: [settings.background, []] + background: [settings.background, []], + padding: [settings.padding, []] }); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.html index 180340881d..c6f65cb5e9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.html @@ -78,5 +78,11 @@ [layout]="statusWidgetSettingsForm.get('layout').value" formControlName="offState"> +
+
{{ 'widget-config.card-padding' | translate }}
+ + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts index 03da985a0e..1130b58b21 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/indicator/status-widget-settings.component.ts @@ -73,7 +73,8 @@ export class StatusWidgetSettingsComponent extends WidgetSettingsComponent { disabledState: [settings.disabledState, []], layout: [settings.layout, []], onState: [settings.onState, []], - offState: [settings.offState, []] + offState: [settings.offState, []], + padding: [settings.padding, []] }); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.html index 9265164c52..5271825ccf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.html @@ -100,5 +100,11 @@
+
+
{{ 'widget-config.card-padding' | translate }}
+ + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts index e6b8880758..2d16a030b7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/weather/wind-speed-direction-widget-settings.component.ts @@ -91,7 +91,8 @@ export class WindSpeedDirectionWidgetSettingsComponent extends WidgetSettingsCom arrowColor: [settings.arrowColor, []], - background: [settings.background, []] + background: [settings.background, []], + padding: [settings.padding, []] }); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.html index 80ca1960f9..0ec08c2a05 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts index 4ce5cf21d7..0381e8531f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts @@ -92,6 +92,7 @@ export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, Aft backgroundStyle$: Observable; overlayStyle: ComponentStyle = {}; + padding: string; shapeResize$: ResizeObserver; @@ -142,6 +143,7 @@ export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, Aft this.backgroundStyle$ = backgroundStyle(this.settings.background, this.imagePipe, this.sanitizer); this.overlayStyle = overlayStyle(this.settings.background.overlay); + this.padding = this.settings.background.overlay.enabled ? undefined : this.settings.padding; this.hasCardClickAction = this.ctx.actionsApi.getActionDescriptors('cardClick').length > 0; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts index 7801f80a17..5c1a5518e8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts @@ -59,6 +59,7 @@ export interface WindSpeedDirectionWidgetSettings { minorTicksColor: string; minorTicksFont: Font; background: BackgroundSettings; + padding: string } export const windSpeedDirectionDefaultSettings: WindSpeedDirectionWidgetSettings = { @@ -101,5 +102,6 @@ export const windSpeedDirectionDefaultSettings: WindSpeedDirectionWidgetSettings color: 'rgba(255,255,255,0.72)', blur: 3 } - } + }, + padding: '12px' }; From 08620e80e4c5c9e207ba6fc036e8b019a200662e Mon Sep 17 00:00:00 2001 From: d2eight Date: Tue, 30 Jul 2024 11:50:53 +0300 Subject: [PATCH 12/80] Some fixes --- .../basic/indicator/status-widget-basic-config.component.ts | 3 +-- .../widget/lib/cards/value-card-widget.component.html | 4 ++-- .../components/widget/lib/indicator/status-widget.models.ts | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts index c54df3321c..0e012cefe7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/config/basic/indicator/status-widget-basic-config.component.ts @@ -29,7 +29,7 @@ import { statusWidgetLayoutImages, statusWidgetLayouts, statusWidgetLayoutTranslations, - StatusWidgetSettings, StatusWidgetStateSettings + StatusWidgetSettings } from '@home/components/widget/lib/indicator/status-widget.models'; @Component({ @@ -66,7 +66,6 @@ export class StatusWidgetBasicConfigComponent extends BasicWidgetConfigComponent protected onConfigSet(configData: WidgetConfigComponentData) { const settings: StatusWidgetSettings = {...statusWidgetDefaultSettings, ...(configData.config.settings || {})}; - this.statusWidgetConfigForm = this.fb.group({ targetDevice: [configData.config.targetDevice, []], diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html index 3d8ebd76b8..814f9f08d8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.html @@ -21,8 +21,8 @@
- - + + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts index 8da94a3739..d9daebba31 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts @@ -202,5 +202,5 @@ export const statusWidgetDefaultSettings: StatusWidgetSettings = { } } }, - padding: '12px' + padding: '16px' }; From db321d92da64e6b978b525e4bf1acea0abd49ec5 Mon Sep 17 00:00:00 2001 From: d2eight Date: Tue, 30 Jul 2024 12:01:02 +0300 Subject: [PATCH 13/80] delete console.log --- .../components/widget/lib/cards/value-card-widget.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts index 440c2d4056..d28f62ee57 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts @@ -140,7 +140,6 @@ export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestro this.labelStyle = textStyle(this.settings.labelFont); this.labelColor = ColorProcessor.fromSettings(this.settings.labelColor); this.valueStyle = textStyle(this.settings.valueFont); - console.log(this.valueStyle); this.valueColor = ColorProcessor.fromSettings(this.settings.valueColor); this.showDate = this.settings.showDate; From 1ebb241520d38eb0834352a391d2bcfc6694c601 Mon Sep 17 00:00:00 2001 From: d2eight Date: Tue, 30 Jul 2024 12:49:51 +0300 Subject: [PATCH 14/80] status widget fix --- .../widget/lib/indicator/status-widget.component.scss | 2 +- .../components/widget/lib/indicator/status-widget.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss index a2e32fcfcc..9585cdb0eb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss @@ -20,7 +20,7 @@ display: flex; align-items: center; justify-content: center; - padding: 0; + padding: 16px; > div:not(.tb-status-widget-overlay), > tb-icon { z-index: 1; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts index 3f85917897..77de5bc39c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts @@ -229,7 +229,7 @@ export class StatusWidgetComponent extends this.showLabel = stateSettings.showLabel && this.layout !== StatusWidgetLayout.icon; this.showStatus = stateSettings.showStatus && this.layout !== StatusWidgetLayout.icon; this.icon = stateSettings.icon; - this.padding = stateSettings.background.overlay.enabled ? undefined : this.settings.padding; + this.padding = stateSettings.backgroundDisabled.overlay.enabled || stateSettings.background.overlay.enabled ? undefined : this.settings.padding; const primaryColor = disabled ? stateSettings.primaryColorDisabled : stateSettings.primaryColor; const secondaryColor = disabled ? stateSettings.secondaryColorDisabled : stateSettings.secondaryColor; From e41b62737133f314259616f68d2084f228c70d3a Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 7 Aug 2024 14:24:53 +0300 Subject: [PATCH 15/80] Renew activation link if less than 15 minutes before expiration --- .../server/controller/UserController.java | 3 ++- .../server/controller/AuthControllerTest.java | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index c76958dabe..234a2096d1 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -85,6 +85,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; @@ -590,7 +591,7 @@ public class UserController extends BaseController { TenantId tenantId = getTenantId(); UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, userId); if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { - if (userCredentials.isActivationTokenExpired()) { + if (System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(15) > userCredentials.getActivateTokenExpTime()) { // renew link if less than 15 minutes before expiration userCredentials = userService.generateUserActivationToken(userCredentials); userCredentials = userService.saveUserCredentials(tenantId, userCredentials); log.debug("[{}][{}] Regenerated expired user activation token", tenantId, userId); diff --git a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java index dba5a84e1b..de60cb61ea 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java @@ -220,6 +220,7 @@ public class AuthControllerTest extends AbstractControllerTest { String initialActivationLink = doGet("/api/user/" + user.getId() + "/activationLink", String.class); String initialActivationToken = StringUtils.substringAfterLast(initialActivationLink, "activateToken="); + // expiring activation token userCredentials.setActivateTokenExpTime(System.currentTimeMillis() - 1); userCredentialsDao.save(tenantId, userCredentials); doGet("/api/noauth/activate?activateToken={activateToken}", initialActivationToken) @@ -229,14 +230,26 @@ public class AuthControllerTest extends AbstractControllerTest { .put("password", "wefewe")).andExpect(status().isBadRequest()) .andExpect(jsonPath("$.message", is("Activation token expired"))); + // checking that activation link is regenerated when requested String regeneratedActivationLink = doGet("/api/user/" + user.getId() + "/activationLink", String.class); - String regeneratedActivationToken = StringUtils.substringAfterLast(regeneratedActivationLink, "activateToken="); - assertThat(regeneratedActivationToken).isNotEqualTo(initialActivationLink); + assertThat(regeneratedActivationLink).isNotEqualTo(initialActivationLink); + + // checking link renewal if less than 15 minutes before expiration + userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); + userCredentials.setActivateTokenExpTime(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(30)); + userCredentialsDao.save(tenantId, userCredentials); + assertThat(doGet("/api/user/" + user.getId() + "/activationLink", String.class)).isEqualTo(regeneratedActivationLink); + userCredentials.setActivateTokenExpTime(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10)); + userCredentialsDao.save(tenantId, userCredentials); + String newActivationLink = doGet("/api/user/" + user.getId() + "/activationLink", String.class); + assertThat(newActivationLink).isNotEqualTo(regeneratedActivationLink); + String newActivationToken = StringUtils.substringAfterLast(newActivationLink, "activateToken="); + userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); assertThat(userCredentials.getActivateTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); doPost("/api/noauth/activate", JacksonUtil.newObjectNode() - .put("activateToken", regeneratedActivationToken) + .put("activateToken", newActivationToken) .put("password", "wefewe")).andExpect(status().isOk()); } From 9e8958b6849afbaf4de4df8a80b4b3709e4a25ce Mon Sep 17 00:00:00 2001 From: Ikko Eltociear Ashimine Date: Wed, 14 Aug 2024 00:39:09 +0900 Subject: [PATCH 16/80] chore: update proto_config.proto accesing -> accessing --- .../transport/coap/src/main/proto/efento/proto_config.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/transport/coap/src/main/proto/efento/proto_config.proto b/common/transport/coap/src/main/proto/efento/proto_config.proto index 25dbec883f..5a82ec078c 100644 --- a/common/transport/coap/src/main/proto/efento/proto_config.proto +++ b/common/transport/coap/src/main/proto/efento/proto_config.proto @@ -31,7 +31,7 @@ message ProtoOutputControlState { uint32 channel_state = 2; } -/* Message containing request data for accesing calibration parameters */ +/* Message containing request data for accessing calibration parameters */ message ProtoCalibrationParameters { /* Request details. Bitmask: */ @@ -349,4 +349,4 @@ message ProtoConfig { /* BLE advertising period configuration. */ ProtoBleAdvertisingPeriod ble_advertising_period = 59; -} \ No newline at end of file +} From 9c68204845094000ebce0e4358578a7658d6baad Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 14 Aug 2024 13:17:35 +0300 Subject: [PATCH 17/80] Add activation link info API --- .../server/controller/UserController.java | 30 +++++++++++++---- .../server/controller/AuthControllerTest.java | 32 +++++++++++++++---- .../common/data/security/UserCredentials.java | 7 +++- 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 234a2096d1..823129d59b 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -229,19 +229,30 @@ public class UserController extends BaseController { User user = checkNotNull(userService.findUserByEmail(getCurrentUser().getTenantId(), email)); accessControlService.checkPermission(getCurrentUser(), Resource.USER, Operation.READ, user.getId(), user); - String activationLink = getActivationLink(user.getId(), request); - mailService.sendActivationEmail(activationLink, email); + ActivationLink activationLink = getActivationLink(user.getId(), request); + mailService.sendActivationEmail(activationLink.value(), email); } - @ApiOperation(value = "Get the activation link (getActivationLink)", + @ApiOperation(value = "Get activation link (getActivationLink)", notes = "Get the activation link for the user. " + "The base url for activation link is configurable in the general settings of system administrator. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") - @RequestMapping(value = "/user/{userId}/activationLink", method = RequestMethod.GET, produces = "text/plain") + @GetMapping(value = "/user/{userId}/activationLink", produces = "text/plain") @ResponseBody public String getActivationLink(@Parameter(description = USER_ID_PARAM_DESCRIPTION) @PathVariable(USER_ID) String strUserId, HttpServletRequest request) throws ThingsboardException { + return getActivationLinkInfo(strUserId, request).value(); + } + + @ApiOperation(value = "Get activation link info (getActivationLinkInfo)", + notes = "Get the activation link info for the user. " + + "The base url for activation link is configurable in the general settings of system administrator. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) + @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") + @GetMapping(value = "/user/{userId}/activationLinkInfo") + public ActivationLink getActivationLinkInfo(@Parameter(description = USER_ID_PARAM_DESCRIPTION) + @PathVariable(USER_ID) String strUserId, + HttpServletRequest request) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); checkUserId(userId, Operation.READ); @@ -587,17 +598,20 @@ public class UserController extends BaseController { userService.removeMobileSession(user.getTenantId(), mobileToken); } - private String getActivationLink(UserId userId, HttpServletRequest request) throws ThingsboardException { + private ActivationLink getActivationLink(UserId userId, HttpServletRequest request) throws ThingsboardException { TenantId tenantId = getTenantId(); UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, userId); if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { - if (System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(15) > userCredentials.getActivateTokenExpTime()) { // renew link if less than 15 minutes before expiration + long ttl = userCredentials.getActivationTokenTtl(); + if (ttl < TimeUnit.MINUTES.toMillis(15)) { // renew link if less than 15 minutes before expiration userCredentials = userService.generateUserActivationToken(userCredentials); userCredentials = userService.saveUserCredentials(tenantId, userCredentials); + ttl = userCredentials.getActivationTokenTtl(); log.debug("[{}][{}] Regenerated expired user activation token", tenantId, userId); } String baseUrl = systemSecurityService.getBaseUrl(tenantId, getCurrentUser().getCustomerId(), request); - return String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken()); + String link = String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken()); + return new ActivationLink(link, ttl); } else { throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); } @@ -609,4 +623,6 @@ public class UserController extends BaseController { } } + record ActivationLink(String value, long ttlMs) {} + } diff --git a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java index de60cb61ea..e4010713d8 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java @@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.data.security.model.SecuritySettings; +import org.thingsboard.server.controller.UserController.ActivationLink; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.dao.user.UserCredentialsDao; import org.thingsboard.server.service.security.auth.rest.LoginRequest; @@ -38,6 +39,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.within; import static org.hamcrest.Matchers.is; import static org.mockito.ArgumentMatchers.anyString; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; @@ -217,8 +219,11 @@ public class AuthControllerTest extends AbstractControllerTest { UserCredentials userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); assertThat(userCredentials.getActivateTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); - String initialActivationLink = doGet("/api/user/" + user.getId() + "/activationLink", String.class); + String initialActivationLink = getActivationLink(user); String initialActivationToken = StringUtils.substringAfterLast(initialActivationLink, "activateToken="); + ActivationLink activationLinkInfo = getActivationLinkInfo(user); + assertThat(TimeUnit.MILLISECONDS.toHours(activationLinkInfo.ttlMs())).isCloseTo(ttl, within(1L)); + assertThat(activationLinkInfo.value()).isEqualTo(initialActivationLink); // expiring activation token userCredentials.setActivateTokenExpTime(System.currentTimeMillis() - 1); @@ -231,19 +236,24 @@ public class AuthControllerTest extends AbstractControllerTest { .andExpect(jsonPath("$.message", is("Activation token expired"))); // checking that activation link is regenerated when requested - String regeneratedActivationLink = doGet("/api/user/" + user.getId() + "/activationLink", String.class); - assertThat(regeneratedActivationLink).isNotEqualTo(initialActivationLink); + ActivationLink regeneratedActivationLink = getActivationLinkInfo(user); + assertThat(regeneratedActivationLink.value()).isNotEqualTo(initialActivationLink); + assertThat(TimeUnit.MILLISECONDS.toHours(regeneratedActivationLink.ttlMs())).isCloseTo(ttl, within(1L)); // checking link renewal if less than 15 minutes before expiration userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); userCredentials.setActivateTokenExpTime(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(30)); userCredentialsDao.save(tenantId, userCredentials); - assertThat(doGet("/api/user/" + user.getId() + "/activationLink", String.class)).isEqualTo(regeneratedActivationLink); + activationLinkInfo = getActivationLinkInfo(user); + assertThat(activationLinkInfo.value()).isEqualTo(regeneratedActivationLink.value()); + assertThat(TimeUnit.MILLISECONDS.toMinutes(activationLinkInfo.ttlMs())).isCloseTo(30, within(1L)); + userCredentials.setActivateTokenExpTime(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10)); userCredentialsDao.save(tenantId, userCredentials); - String newActivationLink = doGet("/api/user/" + user.getId() + "/activationLink", String.class); - assertThat(newActivationLink).isNotEqualTo(regeneratedActivationLink); - String newActivationToken = StringUtils.substringAfterLast(newActivationLink, "activateToken="); + ActivationLink newActivationLink = getActivationLinkInfo(user); + assertThat(newActivationLink.value()).isNotEqualTo(regeneratedActivationLink.value()); + assertThat(TimeUnit.MILLISECONDS.toHours(newActivationLink.ttlMs())).isCloseTo(ttl, within(1L)); + String newActivationToken = StringUtils.substringAfterLast(newActivationLink.value(), "activateToken="); userCredentials = userCredentialsDao.findByUserId(tenantId, user.getUuidId()); assertThat(userCredentials.getActivateTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); @@ -265,4 +275,12 @@ public class AuthControllerTest extends AbstractControllerTest { doPost("/api/admin/securitySettings", securitySettings).andExpect(status().isOk()); } + private String getActivationLink(User user) throws Exception { + return doGet("/api/user/" + user.getId() + "/activationLink", String.class); + } + + private ActivationLink getActivationLinkInfo(User user) throws Exception { + return doGet("/api/user/" + user.getId() + "/activationLinkInfo", ActivationLink.class); + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java index 06645feec3..f6e23b9e1a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java @@ -52,7 +52,12 @@ public class UserCredentials extends BaseDataWithAdditionalInfo activateTokenExpTime; + return getActivationTokenTtl() == 0; + } + + @JsonIgnore + public long getActivationTokenTtl() { + return activateTokenExpTime != null ? Math.max(activateTokenExpTime - System.currentTimeMillis(), 0) : 0; } @JsonIgnore From 455f4e59bee1a48c0df0fa3d79c2e1e1b9f99c83 Mon Sep 17 00:00:00 2001 From: 15608076017 <402106264@qq.com> Date: Tue, 20 Aug 2024 21:46:18 +0800 Subject: [PATCH 18/80] Fixed the problem of getAlarmTypes method query failure in rest-client --- .../java/org/thingsboard/rest/client/RestClient.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index 0aa51402c5..76a5751640 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -507,13 +507,16 @@ public class RestClient implements Closeable { return restTemplate.postForEntity(baseURL + "/api/alarm", alarm, Alarm.class).getBody(); } - public List getAlarmTypes(PageLink pageLink) { + public PageData getAlarmTypes(PageLink pageLink) { + Map params = new HashMap<>(); + addPageLinkToParam(params, pageLink); return restTemplate.exchange( baseURL + "/api/alarm/types?" + getUrlParams(pageLink), HttpMethod.GET, HttpEntity.EMPTY, - new ParameterizedTypeReference>() { - }).getBody(); + new ParameterizedTypeReference>() { + }, + params).getBody(); } public AlarmComment saveAlarmComment(AlarmId alarmId, AlarmComment alarmComment) { From adf8ec31c5f1e3000bd061386a90644e3dfa1cec Mon Sep 17 00:00:00 2001 From: mpetrov Date: Wed, 28 Aug 2024 19:18:23 +0300 Subject: [PATCH 19/80] Added workaround for version compatibility of Gateway MQTT Connectors --- .../device-info-table.component.ts | 6 +- .../mapping-data-keys-panel.component.ts | 4 +- .../mapping-table/mapping-table.component.ts | 23 +- .../mqtt-basic-config.component.ts | 191 ------ .../mqtt-basic-config.abstract.ts | 107 ++++ .../mqtt-basic-config.component.html | 2 +- .../mqtt-basic-config.component.scss | 0 .../mqtt-basic-config.component.ts | 107 ++++ .../mqtt-legacy-basic-config.component.ts | 128 ++++ .../broker-config-control.component.html | 0 .../broker-config-control.component.ts | 2 +- .../opc-ua-basic-config.component.ts | 8 - .../dialog/add-connector-dialog.component.ts | 16 +- .../dialog/mapping-dialog.component.ts | 27 +- .../gateway/gateway-connectors.component.html | 15 +- .../gateway/gateway-connectors.component.scss | 5 + .../gateway/gateway-connectors.component.ts | 27 +- .../lib/gateway/gateway-widget.models.ts | 215 +++++-- .../gateway/pipes/gateway-help-link.pipe.ts | 10 +- .../gateway-connector-version-mapping.util.ts | 66 ++ .../utils/mqtt-version-mapping.util.ts | 279 ++++++++ .../widget/widget-components.module.ts | 8 +- .../connector-default-configs/mqtt.json | 597 ++++++++++++------ 23 files changed, 1341 insertions(+), 502 deletions(-) delete mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{mqtt-basic-config => mqtt/basic-config}/mqtt-basic-config.component.html (93%) rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{mqtt-basic-config => mqtt/basic-config}/mqtt-basic-config.component.scss (100%) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => mqtt}/broker-config-control/broker-config-control.component.html (100%) rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => mqtt}/broker-config-control/broker-config-control.component.ts (97%) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/device-info-table/device-info-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/device-info-table/device-info-table.component.ts index 569f40b185..91432b7353 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/device-info-table/device-info-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/device-info-table/device-info-table.component.ts @@ -42,8 +42,8 @@ import { import { DeviceInfoType, noLeadTrailSpacesRegex, - OPCUaSourceTypes, - SourceTypes, + OPCUaSourceType, + SourceType, SourceTypeTranslationsMap } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { coerceBoolean } from '@shared/decorators/coercion'; @@ -81,7 +81,7 @@ export class DeviceInfoTableComponent extends PageComponent implements ControlVa required = false; @Input() - sourceTypes: Array = Object.values(SourceTypes); + sourceTypes: Array = Object.values(SourceType); deviceInfoTypeValue: any; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-data-keys-panel/mapping-data-keys-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-data-keys-panel/mapping-data-keys-panel.component.ts index 7867a7213f..de289dde2e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-data-keys-panel/mapping-data-keys-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-data-keys-panel/mapping-data-keys-panel.component.ts @@ -42,7 +42,7 @@ import { MappingValueType, mappingValueTypesMap, noLeadTrailSpacesRegex, - OPCUaSourceTypes, + OPCUaSourceType, RpcMethodsMapping, } from '@home/components/widget/lib/gateway/gateway-widget.models'; @@ -73,7 +73,7 @@ export class MappingDataKeysPanelComponent extends PageComponent implements OnIn keysType: MappingKeysType; @Input() - valueTypeKeys: Array = Object.values(MappingValueType); + valueTypeKeys: Array = Object.values(MappingValueType); @Input() valueTypeEnum = MappingValueType; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.ts index 05dcfa88ba..fa8dfa6466 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.ts @@ -40,17 +40,21 @@ import { Validator, } from '@angular/forms'; import { + AttributeUpdate, ConnectorMapping, + ConnectRequest, ConverterConnectorMapping, ConvertorTypeTranslationsMap, DeviceConnectorMapping, + DisconnectRequest, MappingInfo, MappingType, MappingTypeTranslationsMap, MappingValue, - RequestMappingData, + RequestMappingValue, RequestType, - RequestTypesTranslationsMap + RequestTypesTranslationsMap, + ServerSideRpc } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { MappingDialogComponent } from '@home/components/widget/lib/gateway/dialog/mapping-dialog.component'; import { isDefinedAndNotNull, isUndefinedOrNull } from '@core/utils'; @@ -259,16 +263,17 @@ export class MappingTableComponent implements ControlValueAccessor, Validator, A }; case MappingType.REQUESTS: let details: string; - if ((value as RequestMappingData).requestType === RequestType.ATTRIBUTE_UPDATE) { - details = (value as RequestMappingData).requestValue.attributeFilter; - } else if ((value as RequestMappingData).requestType === RequestType.SERVER_SIDE_RPC) { - details = (value as RequestMappingData).requestValue.methodFilter; + const requestValue = value as RequestMappingValue; + if (requestValue.requestType === RequestType.ATTRIBUTE_UPDATE) { + details = (requestValue.requestValue as AttributeUpdate).attributeFilter; + } else if (requestValue.requestType === RequestType.SERVER_SIDE_RPC) { + details = (requestValue.requestValue as ServerSideRpc).methodFilter; } else { - details = (value as RequestMappingData).requestValue.topicFilter; + details = (requestValue.requestValue as ConnectRequest | DisconnectRequest).topicFilter; } return { - requestType: (value as RequestMappingData).requestType, - type: this.translate.instant(RequestTypesTranslationsMap.get((value as RequestMappingData).requestType)), + requestType: (value as RequestMappingValue).requestType, + type: this.translate.instant(RequestTypesTranslationsMap.get((value as RequestMappingValue).requestType)), details }; case MappingType.OPCUA: diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts deleted file mode 100644 index 25f8671201..0000000000 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts +++ /dev/null @@ -1,191 +0,0 @@ -/// -/// Copyright © 2016-2024 The Thingsboard Authors -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// - -import { ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy, TemplateRef } from '@angular/core'; -import { - ControlValueAccessor, - FormBuilder, - FormGroup, - NG_VALIDATORS, - NG_VALUE_ACCESSOR, - ValidationErrors, - Validator, -} from '@angular/forms'; -import { - MappingType, - MQTTBasicConfig, - RequestMappingData, - RequestType, -} from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { SharedModule } from '@shared/shared.module'; -import { CommonModule } from '@angular/common'; -import { takeUntil } from 'rxjs/operators'; -import { Subject } from 'rxjs'; -import { isObject } from 'lodash'; -import { - SecurityConfigComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component'; -import { - WorkersConfigControlComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component'; -import { - BrokerConfigControlComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component'; -import { - MappingTableComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; -import { isDefinedAndNotNull } from '@core/utils'; - -@Component({ - selector: 'tb-mqtt-basic-config', - templateUrl: './mqtt-basic-config.component.html', - changeDetection: ChangeDetectionStrategy.OnPush, - providers: [ - { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => MqttBasicConfigComponent), - multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => MqttBasicConfigComponent), - multi: true - } - ], - standalone: true, - imports: [ - CommonModule, - SharedModule, - SecurityConfigComponent, - WorkersConfigControlComponent, - BrokerConfigControlComponent, - MappingTableComponent, - ], - styleUrls: ['./mqtt-basic-config.component.scss'] -}) - -export class MqttBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy { - - @Input() - generalTabContent: TemplateRef; - - mappingTypes = MappingType; - basicFormGroup: FormGroup; - - private onChange: (value: MQTTBasicConfig) => void; - private onTouched: () => void; - - private destroy$ = new Subject(); - - constructor(private fb: FormBuilder) { - this.basicFormGroup = this.fb.group({ - dataMapping: [], - requestsMapping: [], - broker: [], - workers: [], - }); - - this.basicFormGroup.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(value => { - this.onChange(this.getMappedMQTTConfig(value)); - this.onTouched(); - }); - } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } - - registerOnChange(fn: (value: MQTTBasicConfig) => void): void { - this.onChange = fn; - } - - registerOnTouched(fn: () => void): void { - this.onTouched = fn; - } - - writeValue(basicConfig: MQTTBasicConfig): void { - const { broker, dataMapping = [], requestsMapping } = basicConfig; - const editedBase = { - workers: broker && (broker.maxNumberOfWorkers || broker.maxMessageNumberPerWorker) ? { - maxNumberOfWorkers: broker.maxNumberOfWorkers, - maxMessageNumberPerWorker: broker.maxMessageNumberPerWorker, - } : {}, - dataMapping: dataMapping || [], - broker: broker || {}, - requestsMapping: Array.isArray(requestsMapping) - ? requestsMapping - : this.getRequestDataArray(requestsMapping), - }; - - this.basicFormGroup.setValue(editedBase, {emitEvent: false}); - } - - private getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig { - let { broker, workers, dataMapping, requestsMapping } = basicConfig || {}; - - if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) { - broker = { - ...broker, - ...workers, - }; - } - - if ((requestsMapping as RequestMappingData[])?.length) { - requestsMapping = this.getRequestDataObject(requestsMapping as RequestMappingData[]); - } - - return { broker, workers, dataMapping, requestsMapping }; - } - - validate(): ValidationErrors | null { - return this.basicFormGroup.valid ? null : { - basicFormGroup: {valid: false} - }; - } - - private getRequestDataArray(value: Record): RequestMappingData[] { - const mappingConfigs = []; - - if (isObject(value)) { - Object.keys(value).forEach((configKey: string) => { - for (const mapping of value[configKey]) { - mappingConfigs.push({ - requestType: configKey, - requestValue: mapping - }); - } - }); - } - - return mappingConfigs; - } - - private getRequestDataObject(array: RequestMappingData[]): Record { - return array.reduce((result, { requestType, requestValue }) => { - result[requestType].push(requestValue); - return result; - }, { - connectRequests: [], - disconnectRequests: [], - attributeRequests: [], - attributeUpdates: [], - serverSideRpc: [], - }); - } -} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts new file mode 100644 index 0000000000..12529d942f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts @@ -0,0 +1,107 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { ControlValueAccessor, FormBuilder, FormGroup, ValidationErrors, Validator } from '@angular/forms'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { isObject } from 'lodash'; +import { + MappingType, + MQTTBasicConfig, + MQTTLegacyBasicConfig, + RequestMappingData, + RequestMappingValue, + RequestType +} from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { Directive, OnDestroy } from '@angular/core'; + +@Directive() +export abstract class AbstractMqttBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy { + + basicFormGroup: FormGroup; + mappingTypes = MappingType; + private destroy$ = new Subject(); + private onChange: (value: MQTTBasicConfig | MQTTLegacyBasicConfig) => void; + private onTouched: () => void; + + constructor(protected fb: FormBuilder) { + this.basicFormGroup = this.fb.group({ + mapping: [], + requestsMapping: [], + broker: [], + workers: [], + }); + + this.basicFormGroup.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(value => { + this.onChange(this.getMappedMQTTConfig(value)); + this.onTouched(); + }); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + registerOnChange(fn: (value: MQTTBasicConfig | MQTTLegacyBasicConfig) => void): void { + this.onChange = fn; + } + + registerOnTouched(fn: () => void): void { + this.onTouched = fn; + } + + validate(): ValidationErrors | null { + return this.basicFormGroup.valid ? null : { + basicFormGroup: {valid: false} + }; + } + + protected getRequestDataArray(value: Record): RequestMappingData[] { + const mappingConfigs = []; + + if (isObject(value)) { + Object.keys(value).forEach((configKey: string) => { + for (const mapping of value[configKey]) { + mappingConfigs.push({ + requestType: configKey, + requestValue: mapping + }); + } + }); + } + + return mappingConfigs; + } + + protected getRequestDataObject(array: RequestMappingValue[]): Record { + return array.reduce((result, { requestType, requestValue }) => { + result[requestType].push(requestValue); + return result; + }, { + connectRequests: [], + disconnectRequests: [], + attributeRequests: [], + attributeUpdates: [], + serverSideRpc: [], + }); + } + + abstract writeValue(basicConfig: MQTTBasicConfig | MQTTLegacyBasicConfig): void; + protected abstract getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig | MQTTLegacyBasicConfig; +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.html similarity index 93% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.html rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.html index 9849923218..9ad25aa851 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.html @@ -24,7 +24,7 @@
- +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.scss similarity index 100% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.scss rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.scss diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts new file mode 100644 index 0000000000..c4ebadb03d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts @@ -0,0 +1,107 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component, forwardRef, Input, TemplateRef, ChangeDetectionStrategy } from '@angular/core'; +import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms'; +import { + MQTTBasicConfig, + RequestMappingData, + RequestMappingValue, + RequestType +} from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { + AbstractMqttBasicConfigComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract'; +import { isDefinedAndNotNull } from '@core/utils'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { + SecurityConfigComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component'; +import { + WorkersConfigControlComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component'; +import { + BrokerConfigControlComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component'; +import { + MappingTableComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; + +@Component({ + selector: 'tb-mqtt-basic-config', + templateUrl: './mqtt-basic-config.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MqttBasicConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MqttBasicConfigComponent), + multi: true + } + ], + styleUrls: ['./mqtt-basic-config.component.scss'], + standalone: true, + imports: [ + CommonModule, + SharedModule, + SecurityConfigComponent, + WorkersConfigControlComponent, + BrokerConfigControlComponent, + MappingTableComponent, + ], +}) +export class MqttBasicConfigComponent extends AbstractMqttBasicConfigComponent { + + @Input() + generalTabContent: TemplateRef; + + writeValue(basicConfig: MQTTBasicConfig): void { + const { broker, mapping = [], requestsMapping } = basicConfig; + const editedBase = { + workers: broker && (broker.maxNumberOfWorkers || broker.maxMessageNumberPerWorker) ? { + maxNumberOfWorkers: broker.maxNumberOfWorkers, + maxMessageNumberPerWorker: broker.maxMessageNumberPerWorker, + } : {}, + mapping: mapping || [], + broker: broker || {}, + requestsMapping: this.getRequestDataArray(requestsMapping as Record), + }; + + this.basicFormGroup.setValue(editedBase, {emitEvent: false}); + } + + protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig { + let { broker, workers, mapping, requestsMapping } = basicConfig || {}; + + if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) { + broker = { + ...broker, + ...workers, + }; + } + + if ((requestsMapping as RequestMappingData[])?.length) { + requestsMapping = this.getRequestDataObject(requestsMapping as RequestMappingValue[]); + } + + return { broker, mapping, requestsMapping }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts new file mode 100644 index 0000000000..f499199739 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts @@ -0,0 +1,128 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component, forwardRef, Input, TemplateRef, ChangeDetectionStrategy } from '@angular/core'; +import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms'; +import { + MQTTBasicConfig, + MQTTLegacyBasicConfig, + RequestMappingData, + RequestMappingValue, + RequestType +} from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { MqttVersionMappingUtil } from '@home/components/widget/lib/gateway/utils/mqtt-version-mapping.util'; +import { + AbstractMqttBasicConfigComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract'; +import { isDefinedAndNotNull } from '@core/utils'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { + SecurityConfigComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component'; +import { + WorkersConfigControlComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component'; +import { + BrokerConfigControlComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component'; +import { + MappingTableComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; + +@Component({ + selector: 'tb-mqtt-legacy-basic-config', + templateUrl: './mqtt-basic-config.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MqttLegacyBasicConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => MqttLegacyBasicConfigComponent), + multi: true + } + ], + styleUrls: ['./mqtt-basic-config.component.scss'], + standalone: true, + imports: [ + CommonModule, + SharedModule, + SecurityConfigComponent, + WorkersConfigControlComponent, + BrokerConfigControlComponent, + MappingTableComponent, + ], +}) +export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigComponent { + + @Input() + generalTabContent: TemplateRef; + + writeValue(basicConfig: any): void { + const { + broker, + mapping = [], + connectRequests = [], + disconnectRequests = [], + attributeRequests = [], + attributeUpdates = [], + serverSideRpc = [] + } = basicConfig; + const updatedRequestMapping = MqttVersionMappingUtil.mapRequestsToNewestVersion({ + connectRequests, + disconnectRequests, + attributeRequests, + attributeUpdates, + serverSideRpc + }); + const editedBase = { + workers: broker && (broker.maxNumberOfWorkers || broker.maxMessageNumberPerWorker) ? { + maxNumberOfWorkers: broker.maxNumberOfWorkers, + maxMessageNumberPerWorker: broker.maxMessageNumberPerWorker, + } : {}, + mapping: MqttVersionMappingUtil.mapMappingToNewestVersion(mapping) || [], + broker: broker || {}, + requestsMapping: this.getRequestDataArray(updatedRequestMapping), + }; + + this.basicFormGroup.setValue(editedBase, {emitEvent: false}); + } + + protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTLegacyBasicConfig { + let { broker, workers, mapping, requestsMapping } = basicConfig || {}; + + if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) { + broker = { + ...broker, + ...workers, + }; + } + + if ((requestsMapping as RequestMappingData[])?.length) { + requestsMapping = this.getRequestDataObject(requestsMapping as RequestMappingValue[]); + } + + return { + broker, + mapping: MqttVersionMappingUtil.mapMappingToLegacyVersion(mapping), + ...(MqttVersionMappingUtil.mapRequestsToLegacyVersion(requestsMapping as Record)) + }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.html rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component.html diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component.ts similarity index 97% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component.ts index d4bfdd4694..6f0eadd55f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component.ts @@ -37,7 +37,7 @@ import { TranslateService } from '@ngx-translate/core'; import { generateSecret } from '@core/utils'; import { Subject } from 'rxjs'; import { GatewayPortTooltipPipe } from '@home/components/widget/lib/gateway/pipes/gateway-port-tooltip.pipe'; -import { SecurityConfigComponent } from '../security-config/security-config.component'; +import { SecurityConfigComponent } from '../../security-config/security-config.component'; @Component({ selector: 'tb-broker-config-control', diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.ts index 39198c9696..b6cf4a4081 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.ts @@ -36,12 +36,6 @@ import { Subject } from 'rxjs'; import { SecurityConfigComponent } from '@home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component'; -import { - WorkersConfigControlComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component'; -import { - BrokerConfigControlComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component'; import { MappingTableComponent } from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; @@ -70,8 +64,6 @@ import { CommonModule, SharedModule, SecurityConfigComponent, - WorkersConfigControlComponent, - BrokerConfigControlComponent, MappingTableComponent, OpcServerConfigComponent, ], diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts index eca1497d22..d79a1d3fec 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts @@ -26,12 +26,13 @@ import { AddConnectorConfigData, ConnectorType, CreatedConnectorConfigData, + GatewayConnector, GatewayConnectorDefaultTypesTranslatesMap, GatewayLogLevel, - getDefaultConfig, + GatewayVersionedDefaultConfig, noLeadTrailSpacesRegex } from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { Subject } from 'rxjs'; +import { Observable, Subject } from 'rxjs'; import { ResourcesService } from '@core/services/resources.service'; import { takeUntil, tap } from 'rxjs/operators'; import { helpBaseUrl } from '@shared/models/constants'; @@ -42,7 +43,8 @@ import { helpBaseUrl } from '@shared/models/constants'; styleUrls: ['./add-connector-dialog.component.scss'], providers: [], }) -export class AddConnectorDialogComponent extends DialogComponent> implements OnInit, OnDestroy { +export class AddConnectorDialogComponent + extends DialogComponent> implements OnInit, OnDestroy { connectorForm: UntypedFormGroup; @@ -95,8 +97,8 @@ export class AddConnectorDialogComponent extends DialogComponent { - value.configurationJson = defaultConfig; + this.getDefaultConfig(value.type).subscribe(({current, legacy, ...defaultConfig}: GatewayVersionedDefaultConfig) => { + value.configurationJson = (this.data.gatewayVersion ? current : legacy) ?? defaultConfig; if (this.connectorForm.valid) { this.dialogRef.close(value); } @@ -130,4 +132,8 @@ export class AddConnectorDialogComponent extends DialogComponent { + return this.resourcesService.loadJsonResource(`/assets/metadata/connector-default-configs/${type}.json`); + }; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/mapping-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/mapping-dialog.component.ts index 9e5a43bc17..ef8d7ed7ce 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/mapping-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/mapping-dialog.component.ts @@ -43,15 +43,16 @@ import { MappingType, MappingTypeTranslationsMap, noLeadTrailSpacesRegex, - OPCUaSourceTypes, + OPCUaSourceType, QualityTypes, QualityTypeTranslationsMap, + RequestMappingData, RequestMappingFormValue, RequestType, RequestTypesTranslationsMap, RpcMethod, ServerSideRPCType, - SourceTypes, + SourceType, SourceTypeTranslationsMap, Timeseries } from '@home/components/widget/lib/gateway/gateway-widget.models'; @@ -82,10 +83,10 @@ export class MappingDialogComponent extends DialogComponent; - OPCUaSourceTypesEnum = OPCUaSourceTypes; - sourceTypesEnum = SourceTypes; + sourceTypes: SourceType[] = Object.values(SourceType); + OPCUaSourceTypes = Object.values(OPCUaSourceType) as Array; + OPCUaSourceTypesEnum = OPCUaSourceType; + sourceTypesEnum = SourceType; SourceTypeTranslationsMap = SourceTypeTranslationsMap; requestTypes: RequestType[] = Object.values(RequestType); @@ -230,8 +231,8 @@ export class MappingDialogComponent extends DialogComponent + }; default: return this.data.value as DeviceConnectorMapping; } @@ -349,10 +350,10 @@ export class MappingDialogComponent extends DialogComponent {{ initialConnector?.type ? GatewayConnectorTypesTranslatesMap.get(initialConnector.type) : '' }} {{ 'gateway.configuration' | translate }} + v{{connectorForm.get('configVersion').value}}
@@ -175,10 +176,16 @@
- - + + + + + + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss index f151887c92..5d8c6aad5b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.scss @@ -22,6 +22,11 @@ overflow-x: auto; padding: 0; + .version-placeholder { + color: gray; + font-size: 12px + } + .connector-container { height: 100%; width: 100%; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index e7e4d05e45..0da917312b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -65,6 +65,7 @@ import { AddConnectorDialogComponent } from '@home/components/widget/lib/gateway import { debounceTime, filter, switchMap, take, takeUntil, tap } from 'rxjs/operators'; import { ErrorStateMatcher } from '@angular/material/core'; import { PageData } from '@shared/models/page/page-data'; +import { GatewayConnectorVersionMappingUtil } from './utils/gateway-connector-version-mapping.util'; export class ForceErrorStateMatcher implements ErrorStateMatcher { isErrorState(control: FormControl | null): boolean { @@ -106,6 +107,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie mode: ConnectorConfigurationModes = this.ConnectorConfigurationModes.BASIC; initialConnector: GatewayConnector; + private gatewayVersion: string; private inactiveConnectors: Array; private attributeDataSource: AttributeDatasource; private inactiveConnectorsDataSource: AttributeDatasource; @@ -241,9 +243,13 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie delete value.class; } + if (this.gatewayVersion && !value.configVersion) { + value.configVersion = this.gatewayVersion; + } + value.ts = Date.now(); - return value; + return GatewayConnectorVersionMappingUtil.getMappedByVersion(value, this.gatewayVersion); } private updateData(reload: boolean = false): void { @@ -265,7 +271,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie }); } - isConnectorSynced(attribute: GatewayAttributeData) { + isConnectorSynced(attribute: GatewayAttributeData): boolean { const connectorData = attribute.value; if (!connectorData.ts || attribute.skipSync) { return false; @@ -342,7 +348,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie class: '', configuration: '', configurationJson: {}, - basicConfig: {} + basicConfig: {}, + configVersion: '' }, {emitEvent: false}); this.connectorForm.markAsPristine(); } @@ -475,7 +482,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie value.configurationJson = {} as ConnectorBaseConfig; } value.basicConfig = value.configurationJson; - this.updateConnector(value); + this.updateConnector({...value, configVersion: this.gatewayVersion ?? ''}); this.generate('basicConfig.broker.clientId'); setTimeout(() => this.saveConnector()); }); @@ -485,7 +492,10 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie return this.dialog.open(AddConnectorDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], - data: { dataSourceData: this.dataSource.data } + data: { + dataSourceData: this.dataSource.data, + gatewayVersion: this.gatewayVersion, + } }).afterClosed(); } @@ -528,7 +538,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie class: [''], configuration: [''], configurationJson: [{}, [Validators.required]], - basicConfig: [{}] + basicConfig: [{}], + configVersion: [''], }); this.connectorForm.disable(); } @@ -571,10 +582,12 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie forkJoin([ this.attributeService.getEntityAttributes(this.device, AttributeScope.SHARED_SCOPE, ['active_connectors']), - this.attributeService.getEntityAttributes(this.device, AttributeScope.SERVER_SCOPE, ['inactive_connectors']) + this.attributeService.getEntityAttributes(this.device, AttributeScope.SERVER_SCOPE, ['inactive_connectors']), + this.attributeService.getEntityAttributes(this.device, AttributeScope.CLIENT_SCOPE, ['Version']) ]).pipe(takeUntil(this.destroy$)).subscribe(attributes => { this.activeConnectors = this.parseConnectors(attributes[0]); this.inactiveConnectors = this.parseConnectors(attributes[1]); + this.gatewayVersion = attributes[2][0]?.value; this.updateData(true); }); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 2dde0b8f54..64cdc8e39b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -14,8 +14,6 @@ /// limitations under the License. /// -import { ResourcesService } from '@core/services/resources.service'; -import { Observable } from 'rxjs'; import { helpBaseUrl, ValueTypeData } from '@shared/models/constants'; import { AttributeData } from '@shared/models/telemetry/telemetry.models'; @@ -114,21 +112,37 @@ export interface GatewayAttributeData extends AttributeData { skipSync?: boolean; } -export interface GatewayConnector { +export interface GatewayConnectorBase { name: string; type: ConnectorType; configuration?: string; - configurationJson: ConnectorBaseConfig; - basicConfig?: ConnectorBaseConfig; logLevel: string; key?: string; class?: string; mode?: ConnectorConfigurationModes; + configVersion?: string; +} + +export type GatewayConnector = CurrentGatewayConnector | LegacyGatewayConnector; + +export interface CurrentGatewayConnector extends GatewayConnectorBase { + configurationJson: ConnectorBaseConfig; + basicConfig?: ConnectorBaseConfig; +} + +export interface LegacyGatewayConnector extends GatewayConnectorBase { + configurationJson: ConnectorLegacyBaseConfig; + basicConfig?: ConnectorLegacyBaseConfig; +} + +export interface GatewayVersionedDefaultConfig { + legacy: LegacyGatewayConnector; + current: GatewayConnector; } export interface DataMapping { topicFilter: string; - QoS: string; + QoS: string | number; converter: Converter; } @@ -180,12 +194,14 @@ export interface ConnectorSecurity { mode?: ModeType; } -export type ConnectorMapping = DeviceConnectorMapping | RequestMappingData | ConverterConnectorMapping; +export type ConnectorMapping = DeviceConnectorMapping | RequestMappingValue | ConverterConnectorMapping; export type ConnectorMappingFormValue = DeviceConnectorMapping | RequestMappingFormValue | ConverterMappingFormValue; export type ConnectorBaseConfig = ConnectorBaseInfo | MQTTBasicConfig | OPCBasicConfig | ModbusBasicConfig; +export type ConnectorLegacyBaseConfig = ConnectorBaseInfo | MQTTLegacyBasicConfig; + export interface ConnectorBaseInfo { name: string; id: string; @@ -194,10 +210,21 @@ export interface ConnectorBaseInfo { } export interface MQTTBasicConfig { - dataMapping: ConverterConnectorMapping[]; - requestsMapping: Record | RequestMappingData[]; + mapping: ConverterConnectorMapping[]; + requestsMapping: Record | RequestMappingData[] | RequestMappingValue[]; + broker: BrokerConfig; + workers?: WorkersConfig; +} + +export interface MQTTLegacyBasicConfig { + mapping: LegacyConverterConnectorMapping[]; broker: BrokerConfig; workers?: WorkersConfig; + connectRequests: LegacyRequestMappingData[]; + disconnectRequests: LegacyRequestMappingData[]; + attributeRequests: LegacyRequestMappingData[]; + attributeUpdates: LegacyRequestMappingData[]; + serverSideRpc: LegacyRequestMappingData[]; } export interface OPCBasicConfig { @@ -215,11 +242,11 @@ export interface WorkersConfig { maxMessageNumberPerWorker: number; } -interface DeviceInfo { +export interface ConnectorDeviceInfo { deviceNameExpression: string; - deviceNameExpressionSource: string; + deviceNameExpressionSource: SourceType; deviceProfileExpression: string; - deviceProfileExpressionSource: string; + deviceProfileExpressionSource: SourceType; } export interface Attribute { @@ -252,20 +279,41 @@ export interface AttributesUpdate { export interface Converter { type: ConvertorType; - deviceNameJsonExpression: string; - deviceTypeJsonExpression: string; + deviceInfo?: ConnectorDeviceInfo; sendDataOnlyOnChange: boolean; timeout: number; - attributes: Attribute[]; - timeseries: Timeseries[]; + attributes?: Attribute[]; + timeseries?: Timeseries[]; + extension?: string; + cached?: boolean; + extensionConfig?: Record; +} + +export interface LegacyConverter extends Converter { + deviceNameJsonExpression?: string; + deviceTypeJsonExpression?: string; + deviceNameTopicExpression?: string; + deviceTypeTopicExpression?: string; + deviceNameExpression?: string; + deviceNameExpressionSource?: string; + deviceTypeExpression?: string; + deviceProfileExpression?: string; + deviceProfileExpressionSource?: string; + ['extension-config']?: Record; } export interface ConverterConnectorMapping { topicFilter: string; - subscriptionQos?: string; + subscriptionQos?: string | number; converter: Converter; } +export interface LegacyConverterConnectorMapping { + topicFilter: string; + subscriptionQos?: string | number; + converter: LegacyConverter; +} + export type ConverterMappingFormValue = Omit & { converter: { type: ConvertorType; @@ -274,8 +322,8 @@ export type ConverterMappingFormValue = Omit; + gatewayVersion: string; } export interface CreatedConnectorConfigData { @@ -590,13 +639,13 @@ export const ConvertorTypeTranslationsMap = new Map( ] ); -export enum SourceTypes { +export enum SourceType { MSG = 'message', TOPIC = 'topic', CONST = 'constant' } -export enum OPCUaSourceTypes { +export enum OPCUaSourceType { PATH = 'path', IDENTIFIER = 'identifier', CONST = 'constant' @@ -607,33 +656,116 @@ export enum DeviceInfoType { PARTIAL = 'partial' } -export const SourceTypeTranslationsMap = new Map( +export const SourceTypeTranslationsMap = new Map( [ - [SourceTypes.MSG, 'gateway.source-type.msg'], - [SourceTypes.TOPIC, 'gateway.source-type.topic'], - [SourceTypes.CONST, 'gateway.source-type.const'], - [OPCUaSourceTypes.PATH, 'gateway.source-type.path'], - [OPCUaSourceTypes.IDENTIFIER, 'gateway.source-type.identifier'], - [OPCUaSourceTypes.CONST, 'gateway.source-type.const'] + [SourceType.MSG, 'gateway.source-type.msg'], + [SourceType.TOPIC, 'gateway.source-type.topic'], + [SourceType.CONST, 'gateway.source-type.const'], + [OPCUaSourceType.PATH, 'gateway.source-type.path'], + [OPCUaSourceType.IDENTIFIER, 'gateway.source-type.identifier'], + [OPCUaSourceType.CONST, 'gateway.source-type.const'] ] ); -export interface RequestMappingData { +export interface RequestMappingValue { requestType: RequestType; - requestValue: RequestDataItem; + requestValue: RequestMappingData; } -export type RequestMappingFormValue = Omit & { - requestValue: Record; -}; - -export interface RequestDataItem { - type: string; - details: string; +export interface RequestMappingFormValue { requestType: RequestType; - methodFilter?: string; - attributeFilter?: string; - topicFilter?: string; + requestValue: Record; +} + +export type RequestMappingData = ConnectRequest | DisconnectRequest | AttributeRequest | AttributeUpdate | ServerSideRpc; + +export type LegacyRequestMappingData = + LegacyConnectRequest + | LegacyDisconnectRequest + | LegacyAttributeRequest + | LegacyAttributeUpdate + | LegacyServerSideRpc; + +export interface ConnectRequest { + topicFilter: string; + deviceInfo: ConnectorDeviceInfo; +} + +export interface DisconnectRequest { + topicFilter: string; + deviceInfo: ConnectorDeviceInfo; +} + +export interface AttributeRequest { + retain: boolean; + topicFilter: string; + deviceInfo: ConnectorDeviceInfo; + attributeNameExpressionSource: SourceType; + attributeNameExpression: string; + topicExpression: string; + valueExpression: string; +} + +export interface AttributeUpdate { + retain: boolean; + deviceNameFilter: string; + attributeFilter: string; + topicExpression: string; + valueExpression: string; +} + +export interface ServerSideRpc { + type: ServerSideRpcType; + deviceNameFilter: string; + methodFilter: string; + requestTopicExpression: string; + responseTopicExpression?: string; + responseTopicQoS?: number; + responseTimeout?: number; + valueExpression: string; +} + +export enum ServerSideRpcType { + WithResponse = 'twoWay', + WithoutResponse = 'oneWay' +} + +export interface LegacyConnectRequest { + topicFilter: string; + deviceNameJsonExpression?: string; + deviceNameTopicExpression?: string; +} + +interface LegacyDisconnectRequest { + topicFilter: string; + deviceNameJsonExpression?: string; + deviceNameTopicExpression?: string; +} + +interface LegacyAttributeRequest { + retain: boolean; + topicFilter: string; + deviceNameJsonExpression: string; + attributeNameJsonExpression: string; + topicExpression: string; + valueExpression: string; +} + +interface LegacyAttributeUpdate { + retain: boolean; + deviceNameFilter: string; + attributeFilter: string; + topicExpression: string; + valueExpression: string; +} + +interface LegacyServerSideRpc { + deviceNameFilter: string; + methodFilter: string; + requestTopicExpression: string; + responseTopicExpression?: string; + responseTimeout?: number; + valueExpression: string; } export enum RequestType { @@ -707,9 +839,6 @@ export enum ServerSideRPCType { TWO_WAY = 'twoWay' } -export const getDefaultConfig = (resourcesService: ResourcesService, type: string): Observable => - resourcesService.loadJsonResource(`/assets/metadata/connector-default-configs/${type}.json`); - export enum MappingValueType { STRING = 'string', INTEGER = 'integer', diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/pipes/gateway-help-link.pipe.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/pipes/gateway-help-link.pipe.ts index 0fec377860..06526ce08e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/pipes/gateway-help-link.pipe.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/pipes/gateway-help-link.pipe.ts @@ -17,8 +17,8 @@ import { Pipe, PipeTransform } from '@angular/core'; import { MappingValueType, - OPCUaSourceTypes, - SourceTypes + OPCUaSourceType, + SourceType } from '@home/components/widget/lib/gateway/gateway-widget.models'; @Pipe({ @@ -26,9 +26,9 @@ import { standalone: true, }) export class GatewayHelpLinkPipe implements PipeTransform { - transform(field: string, sourceType: SourceTypes | OPCUaSourceTypes, sourceTypes?: Array ): string { - if (!sourceTypes || sourceTypes?.includes(OPCUaSourceTypes.PATH)) { - if (sourceType !== OPCUaSourceTypes.CONST) { + transform(field: string, sourceType: SourceType | OPCUaSourceType, sourceTypes?: Array ): string { + if (!sourceTypes || sourceTypes?.includes(OPCUaSourceType.PATH)) { + if (sourceType !== OPCUaSourceType.CONST) { return `widget/lib/gateway/${field}-${sourceType}_fn`; } else { return; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts new file mode 100644 index 0000000000..6a48b5e64b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts @@ -0,0 +1,66 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { + ConnectorType, + GatewayConnector, + LegacyGatewayConnector, +} from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { MqttVersionMappingUtil } from './mqtt-version-mapping.util'; + +export class GatewayConnectorVersionMappingUtil { + + static getMappedByVersion(connector: GatewayConnector, gatewayVersion: string): GatewayConnector { + switch (connector.type) { + case ConnectorType.MQTT: + return this.getMappedMQTTByVersion(connector, gatewayVersion); + default: + return connector; + } + } + + private static getMappedMQTTByVersion( + connector: GatewayConnector | LegacyGatewayConnector, + gatewayVersion: string + ): GatewayConnector | LegacyGatewayConnector { + if (this.isVersionUpdateNeeded(gatewayVersion, connector.configVersion)) { + return this.isGatewayOutdated(gatewayVersion, connector.configVersion) + ? MqttVersionMappingUtil.getLegacyVersion(connector) + : MqttVersionMappingUtil.getNewestVersion(connector); + } + return connector; + } + + private static isGatewayOutdated(gatewayVersion: string, configVersion: string): boolean { + if (!gatewayVersion || !configVersion) { + return false; + } + + return this.parseVersion(configVersion) > this.parseVersion(gatewayVersion); + } + + private static isVersionUpdateNeeded(configVersion: string, gatewayVersion: string): boolean { + if (!gatewayVersion || !configVersion) { + return false; + } + + return this.parseVersion(configVersion) !== this.parseVersion(gatewayVersion); + } + + private static parseVersion(version: string): number { + return Number(version?.replace(/\./g, '')); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts new file mode 100644 index 0000000000..e32d020730 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts @@ -0,0 +1,279 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { deleteNullProperties, isEqual } from '@core/utils'; +import { + AttributeRequest, + ConnectorDeviceInfo, + Converter, + ConverterConnectorMapping, + ConvertorType, + CurrentGatewayConnector, + GatewayConnector, + LegacyConverter, + LegacyConverterConnectorMapping, + LegacyGatewayConnector, + LegacyRequestMappingData, + MQTTBasicConfig, + MQTTLegacyBasicConfig, + RequestMappingData, + RequestType, + ServerSideRpc, + ServerSideRpcType, + SourceType +} from '@home/components/widget/lib/gateway/gateway-widget.models'; + +export class MqttVersionMappingUtil { + + static readonly mqttRequestTypeKeys = Object.values(RequestType); + static readonly mqttRequestMappingOldFields = + ['attributeNameJsonExpression', 'deviceNameJsonExpression', 'deviceNameTopicExpression', 'extension-config']; + static readonly mqttRequestMappingNewFields = + ['attributeNameExpressionSource', 'responseTopicQoS', 'extensionConfig']; + + static getNewestVersion(mqttConnector: GatewayConnector): CurrentGatewayConnector { + const { + connectRequests, + disconnectRequests, + attributeRequests, + attributeUpdates, + serverSideRpc + } = mqttConnector.configurationJson as MQTTLegacyBasicConfig; + let configurationJson = { + ...mqttConnector.configurationJson, + requestsMapping: this.mapRequestsToNewestVersion({ + connectRequests, + disconnectRequests, + attributeRequests, + attributeUpdates, + serverSideRpc + }), + mapping: this.mapMappingToNewestVersion((mqttConnector.configurationJson as MQTTLegacyBasicConfig).mapping), + }; + + this.mqttRequestTypeKeys.forEach((key: RequestType) => { + const { [key]: removedKey, ...rest } = configurationJson as MQTTLegacyBasicConfig; + configurationJson = { ...rest } as any; + }); + + this.cleanUpConfigJson(configurationJson as MQTTBasicConfig); + + return { + ...mqttConnector, + configurationJson + } as CurrentGatewayConnector; + } + + static getLegacyVersion(mqttConnector: GatewayConnector): LegacyGatewayConnector { + const { requestsMapping, mapping, ...restConfig } = mqttConnector.configurationJson as MQTTBasicConfig; + + const updatedRequestsMapping = this.mapRequestsToLegacyVersion(requestsMapping as Record); + const updatedMapping = this.mapMappingToLegacyVersion(mapping); + + return { + ...mqttConnector, + configurationJson: { + ...restConfig, + ...updatedRequestsMapping, + mapping: updatedMapping, + }, + } as LegacyGatewayConnector; + } + + static mapMappingToNewestVersion(mapping: LegacyConverterConnectorMapping[] | ConverterConnectorMapping[]): ConverterConnectorMapping[] { + return mapping?.map(({ converter, topicFilter, subscriptionQos = 1 }) => { + const deviceInfo = converter.deviceInfo ?? this.extractConverterDeviceInfo(converter); + + const newConverter = { + ...converter, + deviceInfo, + extensionConfig: converter.extensionConfig || converter['extension-config'] || null + }; + + this.cleanUpOldFields(newConverter); + + return { converter: newConverter, topicFilter, subscriptionQos }; + }); + } + + static mapRequestsToNewestVersion( + requestMapping: Record + ): Record { + return this.mqttRequestTypeKeys.reduce((acc, key: RequestType) => { + if (!requestMapping[key]) { + return acc; + } + + acc[key] = requestMapping[key].map(value => { + const newValue = this.mapRequestToNewest(value as LegacyRequestMappingData, key); + + this.cleanUpOldFields(newValue as {}); + + return newValue; + }); + + return acc; + }, {}) as Record; + } + + static mapRequestsToLegacyVersion( + requestsMapping: Record + ): Record { + return this.mqttRequestTypeKeys.reduce((acc, key) => { + if (!requestsMapping[key]) { + return acc; + } + + acc[key] = requestsMapping[key].map((value: RequestMappingData) => { + if (key === RequestType.SERVER_SIDE_RPC) { + delete (value as ServerSideRpc).type; + } + + const { attributeNameExpression, deviceInfo, ...rest } = value as AttributeRequest; + + const newValue = { + ...rest, + attributeNameJsonExpression: attributeNameExpression || null, + deviceNameJsonExpression: deviceInfo?.deviceNameExpressionSource !== SourceType.TOPIC ? deviceInfo?.deviceNameExpression : null, + deviceNameTopicExpression: deviceInfo?.deviceNameExpressionSource === SourceType.TOPIC ? deviceInfo?.deviceNameExpression : null, + }; + + this.cleanUpNewFields(newValue); + + return newValue; + }); + + return acc; + }, {}) as Record; + } + + static mapMappingToLegacyVersion( + mapping: ConverterConnectorMapping[] + ): LegacyConverterConnectorMapping[] { + return mapping?.map((converterMapping: ConverterConnectorMapping) => { + const converter = this.mapConverterToLegacy(converterMapping.converter); + + this.cleanUpNewFields(converter as {}); + + return { converter, topicFilter: converterMapping.topicFilter }; + }); + } + + private static mapConverterToLegacy(converter: Converter): LegacyConverter { + const { deviceInfo, ...restConverter } = converter; + + return converter.type !== ConvertorType.BYTES ? { + ...restConverter, + deviceNameJsonExpression: deviceInfo?.deviceNameExpressionSource === SourceType.MSG ? deviceInfo.deviceNameExpression : null, + deviceTypeJsonExpression: + deviceInfo?.deviceProfileExpressionSource === SourceType.MSG ? deviceInfo.deviceProfileExpression : null, + deviceNameTopicExpression: + deviceInfo?.deviceNameExpressionSource !== SourceType.MSG + ? deviceInfo?.deviceNameExpression + : null, + deviceTypeTopicExpression: deviceInfo?.deviceProfileExpressionSource !== SourceType.MSG + ? deviceInfo?.deviceProfileExpression + : null, + } : { + ...restConverter, + deviceNameExpression: deviceInfo.deviceNameExpression, + deviceTypeExpression: deviceInfo.deviceProfileExpression, + ['extension-config']: converter.extensionConfig, + }; + } + + private static cleanUpOldFields(obj: Record): void { + this.mqttRequestMappingOldFields.forEach(field => delete obj[field]); + deleteNullProperties(obj); + } + + private static cleanUpNewFields(obj: Record): void { + this.mqttRequestMappingNewFields.forEach(field => delete obj[field]); + deleteNullProperties(obj); + } + + private static getTypeSourceByValue(value: string): SourceType { + if (value.includes('${')) { + return SourceType.MSG; + } + if (value.includes(`/`)) { + return SourceType.TOPIC; + } + return SourceType.CONST; + } + + private static cleanUpConfigJson(configurationJson: MQTTBasicConfig): void { + if (isEqual(configurationJson.requestsMapping, {})) { + delete configurationJson.requestsMapping; + } + + if (isEqual(configurationJson.mapping, [])) { + delete configurationJson.mapping; + } + } + + private static extractConverterDeviceInfo(converter: LegacyConverter): ConnectorDeviceInfo { + const deviceNameExpression = converter.deviceNameExpression + || converter.deviceNameJsonExpression + || converter.deviceNameTopicExpression + || null; + const deviceNameExpressionSource = converter.deviceNameExpressionSource + ? converter.deviceNameExpressionSource as SourceType + : deviceNameExpression ? this.getTypeSourceByValue(deviceNameExpression) : null; + const deviceProfileExpression = converter.deviceProfileExpression + || converter.deviceTypeTopicExpression + || converter.deviceTypeJsonExpression + || 'default'; + const deviceProfileExpressionSource = converter.deviceProfileExpressionSource + ? converter.deviceProfileExpressionSource as SourceType + : deviceProfileExpression ? this.getTypeSourceByValue(deviceProfileExpression) : null; + + return deviceNameExpression || deviceProfileExpression ? { + deviceNameExpression, + deviceNameExpressionSource, + deviceProfileExpression, + deviceProfileExpressionSource + } : null; + } + + private static mapRequestToNewest(value, key: RequestType): RequestMappingData { + const deviceNameExpression = value.deviceNameJsonExpression || value.deviceNameTopicExpression || null; + const deviceProfileExpression = value.deviceTypeTopicExpression || value.deviceTypeJsonExpression || 'default'; + const deviceProfileExpressionSource = deviceProfileExpression ? this.getTypeSourceByValue(deviceProfileExpression) : null; + const attributeNameExpression = value.attributeNameExpressionSource || value.attributeNameJsonExpression || null; + const responseTopicQoS = key === RequestType.SERVER_SIDE_RPC ? 1 : null; + const type = key === RequestType.SERVER_SIDE_RPC + ? (value as ServerSideRpc).responseTopicExpression + ? ServerSideRpcType.WithResponse + : ServerSideRpcType.WithoutResponse + : null; + + return { + ...value, + attributeNameExpression, + attributeNameExpressionSource: attributeNameExpression ? this.getTypeSourceByValue(attributeNameExpression) : null, + deviceInfo: value.deviceInfo ? value.deviceInfo : deviceNameExpression ? { + deviceNameExpression, + deviceNameExpressionSource: this.getTypeSourceByValue(deviceNameExpression), + deviceProfileExpression, + deviceProfileExpressionSource + } : null, + responseTopicQoS, + type + }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts index 955fd1ecf6..f5f6614962 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts @@ -113,7 +113,7 @@ import { GatewayHelpLinkPipe } from '@home/components/widget/lib/gateway/pipes/g import { EllipsisChipListDirective } from '@shared/directives/ellipsis-chip-list.directive'; import { BrokerConfigControlComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component'; +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component'; import { WorkersConfigControlComponent } from '@home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component'; @@ -122,7 +122,7 @@ import { } from '@home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component'; import { MqttBasicConfigComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component'; +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component'; import { MappingTableComponent } from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; @@ -145,6 +145,9 @@ import { ModbusRpcParametersComponent } from '@home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component'; import { ScadaSymbolWidgetComponent } from '@home/components/widget/lib/scada/scada-symbol-widget.component'; +import { + MqttLegacyBasicConfigComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component'; @NgModule({ declarations: [ @@ -233,6 +236,7 @@ import { ScadaSymbolWidgetComponent } from '@home/components/widget/lib/scada/sc ModbusBasicConfigComponent, EllipsisChipListDirective, ModbusRpcParametersComponent, + MqttLegacyBasicConfigComponent, ], exports: [ EntitiesTableWidgetComponent, diff --git a/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json b/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json index c60e1dd956..17ddbd1285 100644 --- a/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json +++ b/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json @@ -1,218 +1,399 @@ { - "broker": { - "name": "Default Local Broker", - "host": "127.0.0.1", - "port": 1883, - "clientId": "ThingsBoard_gateway", - "version": 5, - "maxMessageNumberPerWorker": 10, - "maxNumberOfWorkers": 100, - "sendDataOnlyOnChange": false, - "security": { - "type": "anonymous" - } - }, - "dataMapping": [ - { - "topicFilter": "sensor/data", - "subscriptionQos": 1, - "converter": { - "type": "json", - "deviceInfo": { - "deviceNameExpressionSource": "message", - "deviceNameExpression": "${serialNumber}", - "deviceProfileExpressionSource": "message", - "deviceProfileExpression": "${sensorType}" + "current": { + "broker": { + "name": "Default Local Broker", + "host": "127.0.0.1", + "port": 1883, + "clientId": "ThingsBoard_gateway", + "version": 5, + "maxMessageNumberPerWorker": 10, + "maxNumberOfWorkers": 100, + "sendDataOnlyOnChange": false, + "security": { + "type": "anonymous" + } }, - "sendDataOnlyOnChange": false, - "timeout": 60000, - "attributes": [ - { - "type": "string", - "key": "model", - "value": "${sensorModel}" - }, - { - "type": "string", - "key": "${sensorModel}", - "value": "on" - } + "mapping": [ + { + "topicFilter": "sensor/data", + "subscriptionQos": 1, + "converter": { + "type": "json", + "deviceInfo": { + "deviceNameExpressionSource": "message", + "deviceNameExpression": "${serialNumber}", + "deviceProfileExpressionSource": "message", + "deviceProfileExpression": "${sensorType}" + }, + "sendDataOnlyOnChange": false, + "timeout": 60000, + "attributes": [ + { + "type": "string", + "key": "model", + "value": "${sensorModel}" + }, + { + "type": "string", + "key": "${sensorModel}", + "value": "on" + } + ], + "timeseries": [ + { + "type": "string", + "key": "temperature", + "value": "${temp}" + }, + { + "type": "double", + "key": "humidity", + "value": "${hum}" + }, + { + "type": "string", + "key": "combine", + "value": "${hum}:${temp}" + } + ] + } + }, + { + "topicFilter": "sensor/+/data", + "subscriptionQos": 1, + "converter": { + "type": "json", + "deviceInfo": { + "deviceNameExpressionSource": "topic", + "deviceNameExpression": "(?<=sensor\/)(.*?)(?=\/data)", + "deviceProfileExpressionSource": "constant", + "deviceProfileExpression": "Thermometer" + }, + "sendDataOnlyOnChange": false, + "timeout": 60000, + "attributes": [ + { + "type": "string", + "key": "model", + "value": "${sensorModel}" + } + ], + "timeseries": [ + { + "type": "double", + "key": "temperature", + "value": "${temp}" + }, + { + "type": "string", + "key": "humidity", + "value": "${hum}" + } + ] + } + }, + { + "topicFilter": "sensor/raw_data", + "subscriptionQos": 1, + "converter": { + "type": "bytes", + "deviceInfo": { + "deviceNameExpressionSource": "message", + "deviceNameExpression": "[0:4]", + "deviceProfileExpressionSource": "constant", + "deviceProfileExpression": "default" + }, + "sendDataOnlyOnChange": false, + "timeout": 60000, + "attributes": [ + { + "type": "raw", + "key": "rawData", + "value": "[:]" + } + ], + "timeseries": [ + { + "type": "raw", + "key": "temp", + "value": "[4:]" + } + ] + } + }, + { + "topicFilter": "custom/sensors/+", + "subscriptionQos": 1, + "converter": { + "type": "custom", + "extension": "CustomMqttUplinkConverter", + "cached": true, + "extensionConfig": { + "temperature": 2, + "humidity": 2, + "batteryLevel": 1 + } + } + } ], - "timeseries": [ - { - "type": "string", - "key": "temperature", - "value": "${temp}" - }, - { - "type": "double", - "key": "humidity", - "value": "${hum}" - }, - { - "type": "string", - "key": "combine", - "value": "${hum}:${temp}" - } - ] - } + "requestsMapping": { + "connectRequests": [ + { + "topicFilter": "sensor/connect", + "deviceInfo": { + "deviceNameExpressionSource": "message", + "deviceNameExpression": "${serialNumber}", + "deviceProfileExpressionSource": "constant", + "deviceProfileExpression": "Thermometer" + } + }, + { + "topicFilter": "sensor/+/connect", + "deviceInfo": { + "deviceNameExpressionSource": "topic", + "deviceNameExpression": "(?<=sensor\/)(.*?)(?=\/connect)", + "deviceProfileExpressionSource": "constant", + "deviceProfileExpression": "Thermometer" + } + } + ], + "disconnectRequests": [ + { + "topicFilter": "sensor/disconnect", + "deviceInfo": { + "deviceNameExpressionSource": "message", + "deviceNameExpression": "${serialNumber}" + } + }, + { + "topicFilter": "sensor/+/disconnect", + "deviceInfo": { + "deviceNameExpressionSource": "topic", + "deviceNameExpression": "(?<=sensor\/)(.*?)(?=\/connect)" + } + } + ], + "attributeRequests": [ + { + "retain": false, + "topicFilter": "v1/devices/me/attributes/request", + "deviceInfo": { + "deviceNameExpressionSource": "message", + "deviceNameExpression": "${serialNumber}" + }, + "attributeNameExpressionSource": "message", + "attributeNameExpression": "${versionAttribute}, ${pduAttribute}", + "topicExpression": "devices/${deviceName}/attrs", + "valueExpression": "${attributeKey}: ${attributeValue}" + } + ], + "attributeUpdates": [ + { + "retain": true, + "deviceNameFilter": ".*", + "attributeFilter": "firmwareVersion", + "topicExpression": "sensor/${deviceName}/${attributeKey}", + "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" + } + ], + "serverSideRpc": [ + { + "type": "twoWay", + "deviceNameFilter": ".*", + "methodFilter": "echo", + "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", + "responseTopicExpression": "sensor/${deviceName}/response/${methodName}/${requestId}", + "responseTopicQoS": 1, + "responseTimeout": 10000, + "valueExpression": "${params}" + }, + { + "type": "oneWay", + "deviceNameFilter": ".*", + "methodFilter": "no-reply", + "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", + "valueExpression": "${params}" + } + ] + } }, - { - "topicFilter": "sensor/+/data", - "subscriptionQos": 1, - "converter": { - "type": "json", - "deviceInfo": { - "deviceNameExpressionSource": "topic", - "deviceNameExpression": "(?<=sensor\/)(.*?)(?=\/data)", - "deviceProfileExpressionSource": "constant", - "deviceProfileExpression": "Thermometer" + "legacy": { + "broker": { + "name": "Default Local Broker", + "host": "127.0.0.1", + "port": 1883, + "clientId": "ThingsBoard_gateway", + "version": 5, + "maxMessageNumberPerWorker": 10, + "maxNumberOfWorkers": 100, + "sendDataOnlyOnChange": false, + "security": { + "type": "basic", + "username": "user", + "password": "password" + } }, - "sendDataOnlyOnChange": false, - "timeout": 60000, - "attributes": [ - { - "type": "string", - "key": "model", - "value": "${sensorModel}" - } + "mapping": [ + { + "topicFilter": "sensor/data", + "converter": { + "type": "json", + "deviceNameJsonExpression": "${serialNumber}", + "deviceTypeJsonExpression": "${sensorType}", + "sendDataOnlyOnChange": false, + "timeout": 60000, + "attributes": [ + { + "type": "string", + "key": "model", + "value": "${sensorModel}" + }, + { + "type": "string", + "key": "${sensorModel}", + "value": "on" + } + ], + "timeseries": [ + { + "type": "double", + "key": "temperature", + "value": "${temp}" + }, + { + "type": "double", + "key": "humidity", + "value": "${hum}" + }, + { + "type": "string", + "key": "combine", + "value": "${hum}:${temp}" + } + ] + } + }, + { + "topicFilter": "sensor/+/data", + "converter": { + "type": "json", + "deviceNameTopicExpression": "(?<=sensor\/)(.*?)(?=\/data)", + "deviceTypeTopicExpression": "Thermometer", + "sendDataOnlyOnChange": false, + "timeout": 60000, + "attributes": [ + { + "type": "string", + "key": "model", + "value": "${sensorModel}" + } + ], + "timeseries": [ + { + "type": "double", + "key": "temperature", + "value": "${temp}" + }, + { + "type": "double", + "key": "humidity", + "value": "${hum}" + } + ] + } + }, + { + "topicFilter": "sensor/raw_data", + "converter": { + "type": "bytes", + "deviceNameExpression": "[0:4]", + "deviceTypeExpression": "default", + "sendDataOnlyOnChange": false, + "timeout": 60000, + "attributes": [ + { + "type": "raw", + "key": "rawData", + "value": "[:]" + } + ], + "timeseries": [ + { + "type": "raw", + "key": "temp", + "value": "[4:]" + } + ] + } + }, + { + "topicFilter": "custom/sensors/+", + "converter": { + "type": "custom", + "extension": "CustomMqttUplinkConverter", + "cached": true, + "extension-config": { + "temperatureBytes": 2, + "humidityBytes": 2, + "batteryLevelBytes": 1 + } + } + } ], - "timeseries": [ - { - "type": "double", - "key": "temperature", - "value": "${temp}" - }, - { - "type": "string", - "key": "humidity", - "value": "${hum}" - } - ] - } - }, - { - "topicFilter": "sensor/raw_data", - "subscriptionQos": 1, - "converter": { - "type": "bytes", - "deviceInfo": { - "deviceNameExpressionSource": "message", - "deviceNameExpression": "[0:4]", - "deviceProfileExpressionSource": "constant", - "deviceProfileExpression": "default" - }, - "sendDataOnlyOnChange": false, - "timeout": 60000, - "attributes": [ - { - "type": "raw", - "key": "rawData", - "value": "[:]" - } + "connectRequests": [ + { + "topicFilter": "sensor/connect", + "deviceNameJsonExpression": "${serialNumber}" + }, + { + "topicFilter": "sensor/+/connect", + "deviceNameTopicExpression": "(?<=sensor\/)(.*?)(?=\/connect)" + } + ], + "disconnectRequests": [ + { + "topicFilter": "sensor/disconnect", + "deviceNameJsonExpression": "${serialNumber}" + }, + { + "topicFilter": "sensor/+/disconnect", + "deviceNameTopicExpression": "(?<=sensor\/)(.*?)(?=\/disconnect)" + } + ], + "attributeRequests": [ + { + "retain": false, + "topicFilter": "v1/devices/me/attributes/request", + "deviceNameJsonExpression": "${serialNumber}", + "attributeNameJsonExpression": "${versionAttribute}, ${pduAttribute}", + "topicExpression": "devices/${deviceName}/attrs", + "valueExpression": "${attributeKey}: ${attributeValue}" + } ], - "timeseries": [ - { - "type": "raw", - "key": "temp", - "value": "[4:]" - } + "attributeUpdates": [ + { + "retain": true, + "deviceNameFilter": ".*", + "attributeFilter": "firmwareVersion", + "topicExpression": "sensor/${deviceName}/${attributeKey}", + "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" + } + ], + "serverSideRpc": [ + { + "deviceNameFilter": ".*", + "methodFilter": "echo", + "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", + "responseTopicExpression": "sensor/${deviceName}/response/${methodName}/${requestId}", + "responseTimeout": 10000, + "valueExpression": "${params}" + }, + { + "deviceNameFilter": ".*", + "methodFilter": "no-reply", + "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", + "valueExpression": "${params}" + } ] - } - }, - { - "topicFilter": "custom/sensors/+", - "subscriptionQos": 1, - "converter": { - "type": "custom", - "extension": "CustomMqttUplinkConverter", - "cached": true, - "extensionConfig": { - "temperature": 2, - "humidity": 2, - "batteryLevel": 1 - } - } - } - ], - "requestsMapping": { - "connectRequests": [ - { - "topicFilter": "sensor/connect", - "deviceInfo": { - "deviceNameExpressionSource": "message", - "deviceNameExpression": "${serialNumber}", - "deviceProfileExpressionSource": "constant", - "deviceProfileExpression": "Thermometer" - } - }, - { - "topicFilter": "sensor/+/connect", - "deviceInfo": { - "deviceNameExpressionSource": "topic", - "deviceNameExpression": "(?<=sensor\/)(.*?)(?=\/connect)", - "deviceProfileExpressionSource": "constant", - "deviceProfileExpression": "Thermometer" - } - } - ], - "disconnectRequests": [ - { - "topicFilter": "sensor/disconnect", - "deviceInfo": { - "deviceNameExpressionSource": "message", - "deviceNameExpression": "${serialNumber}" - } - }, - { - "topicFilter": "sensor/+/disconnect", - "deviceInfo": { - "deviceNameExpressionSource": "topic", - "deviceNameExpression": "(?<=sensor\/)(.*?)(?=\/connect)" - } - } - ], - "attributeRequests": [ - { - "retain": false, - "topicFilter": "v1/devices/me/attributes/request", - "deviceInfo": { - "deviceNameExpressionSource": "message", - "deviceNameExpression": "${serialNumber}" - }, - "attributeNameExpressionSource": "message", - "attributeNameExpression": "${versionAttribute}, ${pduAttribute}", - "topicExpression": "devices/${deviceName}/attrs", - "valueExpression": "${attributeKey}: ${attributeValue}" - } - ], - "attributeUpdates": [ - { - "retain": true, - "deviceNameFilter": ".*", - "attributeFilter": "firmwareVersion", - "topicExpression": "sensor/${deviceName}/${attributeKey}", - "valueExpression": "{\"${attributeKey}\":\"${attributeValue}\"}" - } - ], - "serverSideRpc": [ - { - "type": "twoWay", - "deviceNameFilter": ".*", - "methodFilter": "echo", - "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", - "responseTopicExpression": "sensor/${deviceName}/response/${methodName}/${requestId}", - "responseTopicQoS": 1, - "responseTimeout": 10000, - "valueExpression": "${params}" - }, - { - "type": "oneWay", - "deviceNameFilter": ".*", - "methodFilter": "no-reply", - "requestTopicExpression": "sensor/${deviceName}/request/${methodName}/${requestId}", - "valueExpression": "${params}" } - ] - } } From 33c8cc405058f1a9f42cb90adb7a8ef20d8a4829 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Wed, 28 Aug 2024 19:27:44 +0300 Subject: [PATCH 20/80] refactoring --- .../mqtt/basic-config/mqtt-legacy-basic-config.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts index f499199739..92e4e5b4b5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts @@ -75,7 +75,7 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo @Input() generalTabContent: TemplateRef; - writeValue(basicConfig: any): void { + writeValue(basicConfig: MQTTLegacyBasicConfig): void { const { broker, mapping = [], From a6f79b51def3379519d38a5687fe8e44daef8ee3 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 29 Aug 2024 11:47:57 +0300 Subject: [PATCH 21/80] refactoring --- .../widget/lib/gateway/gateway-connectors.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index 0da917312b..c2ee0c8d62 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -763,6 +763,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie case ConnectorType.OPCUA: case ConnectorType.MODBUS: this.connectorForm.get('mode').setValue(connector.mode || ConnectorConfigurationModes.BASIC, {emitEvent: false}); + this.connectorForm.get('configVersion').setValue(connector.configVersion, {emitEvent: false}); setTimeout(() => { this.connectorForm.patchValue(connector, {emitEvent: false}); this.connectorForm.markAsPristine(); From 7433b156788e4bd147e002872b872671c639000b Mon Sep 17 00:00:00 2001 From: devaskim Date: Tue, 3 Sep 2024 14:48:03 +0500 Subject: [PATCH 22/80] Added Event and Audit Logs services to services map. --- ui-ngx/src/app/modules/home/models/services.map.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/models/services.map.ts b/ui-ngx/src/app/modules/home/models/services.map.ts index cca04d8dc9..073bbd5b43 100644 --- a/ui-ngx/src/app/modules/home/models/services.map.ts +++ b/ui-ngx/src/app/modules/home/models/services.map.ts @@ -50,6 +50,8 @@ import { TenantService } from '@core/http/tenant.service'; import { TenantProfileService } from '@core/http/tenant-profile.service'; import { UiSettingsService } from '@core/http/ui-settings.service'; import { UsageInfoService } from '@core/http/usage-info.service'; +import { EventService } from '@core/http/event.service'; +import { AuditLogService } from '@core/http/audit-log.service'; export const ServicesMap = new Map>( [ @@ -87,6 +89,8 @@ export const ServicesMap = new Map>( ['userSettingsService', UserSettingsService], ['uiSettingsService', UiSettingsService], ['usageInfoService', UsageInfoService], - ['notificationService', NotificationService] + ['notificationService', NotificationService], + ['eventService', EventService], + ['auditLogService', AuditLogService] ] ); From f6a1c14353cfd0f49b2104534db8fcfc1df85d46 Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 4 Sep 2024 16:45:58 +0300 Subject: [PATCH 23/80] Fix last activity not being reported when activity reporting period ends --- .../scheduler/DefaultSchedulerComponent.java | 25 +++-- .../DefaultSchedulerComponentTest.java | 95 ++++++++++++++++++ .../activity/AbstractActivityManager.java | 97 ++++++++++--------- .../FirstAndLastEventActivityStrategy.java | 2 + .../strategy/FirstEventActivityStrategy.java | 2 + 5 files changed, 171 insertions(+), 50 deletions(-) create mode 100644 common/queue/src/test/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponentTest.java diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java b/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java index 9dc2785005..7526326dbf 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java @@ -15,25 +15,29 @@ */ package org.thingsboard.server.queue.scheduler; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.common.util.ThingsBoardThreadFactory; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.PreDestroy; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +@Slf4j @Component public class DefaultSchedulerComponent implements SchedulerComponent { - protected ScheduledExecutorService schedulerExecutor; + private static final String SCHEDULER_NAME = "queue-scheduler"; + + private ScheduledExecutorService schedulerExecutor; @PostConstruct public void init() { - this.schedulerExecutor = Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName("queue-scheduler")); + schedulerExecutor = Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName(SCHEDULER_NAME)); } @PreDestroy @@ -52,10 +56,19 @@ public class DefaultSchedulerComponent implements SchedulerComponent { } public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { - return schedulerExecutor.scheduleAtFixedRate(command, initialDelay, period, unit); + return schedulerExecutor.scheduleAtFixedRate(() -> runSafely(command), initialDelay, period, unit); } public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { - return schedulerExecutor.scheduleWithFixedDelay(command, initialDelay, delay, unit); + return schedulerExecutor.scheduleWithFixedDelay(() -> runSafely(command), initialDelay, delay, unit); } + + private void runSafely(Runnable command) { + try { + command.run(); + } catch (Exception e) { + log.error("[{}] Unexpected error occurred while executing task! {}", SCHEDULER_NAME, Thread.currentThread(), e); + } + } + } diff --git a/common/queue/src/test/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponentTest.java b/common/queue/src/test/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponentTest.java new file mode 100644 index 0000000000..cff306c748 --- /dev/null +++ b/common/queue/src/test/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponentTest.java @@ -0,0 +1,95 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.queue.scheduler; + +import org.awaitility.Awaitility; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.assertj.core.api.Assertions.assertThat; + +class DefaultSchedulerComponentTest { + + DefaultSchedulerComponent schedulerComponent; + + @BeforeEach + void setup() { + schedulerComponent = new DefaultSchedulerComponent(); + schedulerComponent.init(); + } + + @AfterEach + void cleanup() { + schedulerComponent.destroy(); + } + + @Test + @DisplayName("scheduleAtFixedRate() should continue periodic execution even if command throws exception") + void scheduleAtFixedRateShouldNotStopPeriodicExecutionWhenCommandThrowsException() { + // GIVEN + var wasExecutedAtLeastOnce = new AtomicBoolean(false); + + Runnable exceptionThrowingCommand = () -> { + try { + throw new RuntimeException("Unexpected exception"); + } finally { + wasExecutedAtLeastOnce.set(true); + } + }; + + // WHEN + ScheduledFuture future = schedulerComponent.scheduleAtFixedRate(exceptionThrowingCommand, 0, 200, TimeUnit.MILLISECONDS); + + // THEN + Awaitility.await().alias("Wait until command is executed at least once") + .atMost(5, TimeUnit.SECONDS) + .until(wasExecutedAtLeastOnce::get); + + assertThat(future.isDone()).as("Periodic execution should not stop after unhandled exception is thrown by the command").isFalse(); + } + + @Test + @DisplayName("scheduleWithFixedDelay() should continue periodic execution even if command throws exception") + void scheduleWithFixedDelayShouldNotStopPeriodicExecutionWhenCommandThrowsException() { + // GIVEN + var wasExecutedAtLeastOnce = new AtomicBoolean(false); + + Runnable exceptionThrowingCommand = () -> { + try { + throw new RuntimeException("Unexpected exception"); + } finally { + wasExecutedAtLeastOnce.set(true); + } + }; + + // WHEN + ScheduledFuture future = schedulerComponent.scheduleWithFixedDelay(exceptionThrowingCommand, 0, 200, TimeUnit.MILLISECONDS); + + // THEN + Awaitility.await().alias("Wait until command is executed at least once") + .atMost(5, TimeUnit.SECONDS) + .until(wasExecutedAtLeastOnce::get); + + assertThat(future.isDone()).as("Periodic execution should not stop after unhandled exception is thrown by the command").isFalse(); + } + +} diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/AbstractActivityManager.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/AbstractActivityManager.java index f754d6f5b1..ac535d28e1 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/AbstractActivityManager.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/AbstractActivityManager.java @@ -69,7 +69,7 @@ public abstract class AbstractActivityManager implements Activity log.error("Failed to process activity event: provided activity key is null."); return; } - log.debug("Received activity event for key: [{}]", key); + log.debug("Received activity event for key: [{}]. Event time: [{}].", key, newLastRecordedTime); var shouldReport = new AtomicBoolean(false); var lastRecordedTime = new AtomicLong(); @@ -94,7 +94,7 @@ public abstract class AbstractActivityManager implements Activity }); if (shouldReport.get() && lastReportedTime.get() < lastRecordedTime.get()) { - log.debug("Going to report first activity event for key: [{}].", key); + log.debug("Going to report first activity event for key: [{}]. Event time: [{}].", key, lastRecordedTime.get()); reportActivity(key, metadata, lastRecordedTime.get(), new ActivityReportCallback<>() { @Override public void onSuccess(Key key, long reportedTime) { @@ -103,7 +103,7 @@ public abstract class AbstractActivityManager implements Activity @Override public void onFailure(Key key, Throwable t) { - log.debug("Failed to report first activity event for key: [{}].", key, t); + log.debug("Failed to report first activity event for key: [{}]. Event time: [{}].", key, lastRecordedTime.get(), t); } }); } @@ -113,50 +113,59 @@ public abstract class AbstractActivityManager implements Activity public void onReportingPeriodEnd() { log.debug("Going to end reporting period."); for (Map.Entry entry : states.entrySet()) { - var key = entry.getKey(); - var stateWrapper = entry.getValue(); - var currentState = stateWrapper.getState(); - - long lastRecordedTime = currentState.getLastRecordedTime(); - long lastReportedTime = stateWrapper.getLastReportedTime(); - var metadata = currentState.getMetadata(); - - boolean hasExpired; - boolean shouldReport; - - var updatedState = updateState(key, currentState); - if (updatedState != null) { - stateWrapper.setState(updatedState); - lastRecordedTime = updatedState.getLastRecordedTime(); - metadata = updatedState.getMetadata(); - hasExpired = hasExpired(lastRecordedTime); - shouldReport = stateWrapper.getStrategy().onReportingPeriodEnd(); - } else { - states.remove(key); - hasExpired = false; - shouldReport = true; + Key key = entry.getKey(); + ActivityStateWrapper stateWrapper = entry.getValue(); + try { + reportLastEvent(key, stateWrapper); + } catch (Exception e) { + log.error("Failed to report last activity event on reporting period end for key: [{}]. State: [{}].", key, stateWrapper, e); } + } + } - if (hasExpired) { - states.remove(key); - onStateExpiry(key, metadata); - shouldReport = true; - } + private void reportLastEvent(Key key, ActivityStateWrapper stateWrapper) { + var currentState = stateWrapper.getState(); + + long lastRecordedTime = currentState.getLastRecordedTime(); + long lastReportedTime = stateWrapper.getLastReportedTime(); + var metadata = currentState.getMetadata(); + + boolean hasExpired; + boolean shouldReport; + + var updatedState = updateState(key, currentState); + if (updatedState != null) { + stateWrapper.setState(updatedState); + lastRecordedTime = updatedState.getLastRecordedTime(); + metadata = updatedState.getMetadata(); + hasExpired = hasExpired(lastRecordedTime); + shouldReport = stateWrapper.getStrategy().onReportingPeriodEnd(); + } else { + states.remove(key); + hasExpired = false; + shouldReport = true; + } - if (shouldReport && lastReportedTime < lastRecordedTime) { - log.debug("Going to report last activity event for key: [{}].", key); - reportActivity(key, metadata, lastRecordedTime, new ActivityReportCallback<>() { - @Override - public void onSuccess(Key key, long reportedTime) { - updateLastReportedTime(key, reportedTime); - } - - @Override - public void onFailure(Key key, Throwable t) { - log.debug("Failed to report last activity event for key: [{}].", key, t); - } - }); - } + if (hasExpired) { + states.remove(key); + onStateExpiry(key, metadata); + shouldReport = true; + } + + if (shouldReport && lastReportedTime < lastRecordedTime) { + long timeToReport = lastRecordedTime; + log.debug("Going to report last activity event for key: [{}]. Event time: [{}].", key, timeToReport); + reportActivity(key, metadata, timeToReport, new ActivityReportCallback<>() { + @Override + public void onSuccess(Key key, long reportedTime) { + updateLastReportedTime(key, reportedTime); + } + + @Override + public void onFailure(Key key, Throwable t) { + log.debug("Failed to report last activity event for key: [{}]. Event time: [{}].", key, timeToReport, t); + } + }); } } diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstAndLastEventActivityStrategy.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstAndLastEventActivityStrategy.java index a5a59046ae..9ced9bd90b 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstAndLastEventActivityStrategy.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstAndLastEventActivityStrategy.java @@ -16,7 +16,9 @@ package org.thingsboard.server.common.transport.activity.strategy; import lombok.EqualsAndHashCode; +import lombok.ToString; +@ToString @EqualsAndHashCode public final class FirstAndLastEventActivityStrategy implements ActivityStrategy { diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstEventActivityStrategy.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstEventActivityStrategy.java index 5353635c45..3b5d9dfc8d 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstEventActivityStrategy.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/activity/strategy/FirstEventActivityStrategy.java @@ -16,7 +16,9 @@ package org.thingsboard.server.common.transport.activity.strategy; import lombok.EqualsAndHashCode; +import lombok.ToString; +@ToString @EqualsAndHashCode public final class FirstEventActivityStrategy implements ActivityStrategy { From 39049eecd95fb928990944a9726e9557cdb82aaf Mon Sep 17 00:00:00 2001 From: Dmytro Skarzhynets Date: Wed, 4 Sep 2024 17:11:53 +0300 Subject: [PATCH 24/80] Remove redundant logging of thread name and scheduler name --- .../server/queue/scheduler/DefaultSchedulerComponent.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java b/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java index 7526326dbf..095e5b18dc 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/scheduler/DefaultSchedulerComponent.java @@ -31,13 +31,11 @@ import java.util.concurrent.TimeUnit; @Component public class DefaultSchedulerComponent implements SchedulerComponent { - private static final String SCHEDULER_NAME = "queue-scheduler"; - private ScheduledExecutorService schedulerExecutor; @PostConstruct public void init() { - schedulerExecutor = Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName(SCHEDULER_NAME)); + schedulerExecutor = Executors.newSingleThreadScheduledExecutor(ThingsBoardThreadFactory.forName("queue-scheduler")); } @PreDestroy @@ -66,8 +64,8 @@ public class DefaultSchedulerComponent implements SchedulerComponent { private void runSafely(Runnable command) { try { command.run(); - } catch (Exception e) { - log.error("[{}] Unexpected error occurred while executing task! {}", SCHEDULER_NAME, Thread.currentThread(), e); + } catch (Throwable t) { + log.error("Unexpected error occurred while executing task!", t); } } From a8afd8929bf5c9537b8aaa70c7fd9408da65220a Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 4 Sep 2024 17:29:38 +0300 Subject: [PATCH 25/80] Redirect to error page when password reset or activation link is expired --- .../server/controller/AuthController.java | 33 ++++--------------- .../server/controller/BaseController.java | 17 ++++++++-- .../server/controller/AuthControllerTest.java | 6 ++-- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index aa194d688e..a52a80f9f0 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -58,9 +58,6 @@ import org.thingsboard.server.service.security.model.UserPrincipal; import org.thingsboard.server.service.security.model.token.JwtTokenFactory; import org.thingsboard.server.service.security.system.SystemSecurityService; -import java.net.URI; -import java.net.URISyntaxException; - @RestController @TbCoreComponent @RequestMapping("/api") @@ -132,7 +129,7 @@ public class AuthController extends BaseController { notes = "Checks the activation token and forwards user to 'Create Password' page. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Create Password' page and same 'activateToken' specified in the URL parameters. " + "If token is not valid, returns '409 Conflict'. " + - "If token is expired, returns '410 Gone'.") + "If token is expired, redirects to error page.") @GetMapping(value = "/noauth/activate", params = {"activateToken"}) public ResponseEntity checkActivateToken( @Parameter(description = "The activate token string.") @@ -141,18 +138,9 @@ public class AuthController extends BaseController { if (userCredentials == null) { return response(HttpStatus.CONFLICT); } else if (userCredentials.isActivationTokenExpired()) { - return response(HttpStatus.GONE); - } - - String createURI = "/login/createPassword"; - try { - URI location = new URI(createURI + "?activateToken=" + activateToken); - return ResponseEntity.status(HttpStatus.SEE_OTHER) - .location(location).build(); - } catch (URISyntaxException e) { - log.error("Unable to create URI with address [{}]", createURI); - return response(HttpStatus.BAD_REQUEST); + return redirectTo("/activationLinkExpired"); } + return redirectTo("/login/createPassword?activateToken=" + activateToken); } @ApiOperation(value = "Request reset password email (requestResetPasswordByEmail)", @@ -181,7 +169,7 @@ public class AuthController extends BaseController { notes = "Checks the password reset token and forwards user to 'Reset Password' page. " + "If token is valid, returns '303 See Other' (redirect) response code with the correct address of 'Reset Password' page and same 'resetToken' specified in the URL parameters. " + "If token is not valid, returns '409 Conflict'. " + - "If token is expired, returns '410 Gone'.") + "If token is expired, redirects to error page.") @GetMapping(value = "/noauth/resetPassword", params = {"resetToken"}) public ResponseEntity checkResetToken( @Parameter(description = "The reset token string.") @@ -190,21 +178,12 @@ public class AuthController extends BaseController { if (userCredentials == null) { return response(HttpStatus.CONFLICT); } else if (userCredentials.isResetTokenExpired()) { - return response(HttpStatus.GONE); + return redirectTo("/passwordResetLinkExpired"); } if (!rateLimitService.checkRateLimit(LimitedApi.PASSWORD_RESET, userCredentials.getUserId(), defaultLimitsConfiguration)) { return response(HttpStatus.TOO_MANY_REQUESTS); } - - String resetURI = "/login/resetPassword"; - try { - URI location = new URI(resetURI + "?resetToken=" + resetToken); - return ResponseEntity.status(HttpStatus.SEE_OTHER) - .location(location).build(); - } catch (URISyntaxException e) { - log.error("Unable to create URI with address [{}]", resetURI); - return response(HttpStatus.BAD_REQUEST); - } + return redirectTo("/login/resetPassword?resetToken=" + resetToken); } @ApiOperation(value = "Activate User", diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 54d91b6cfb..d266c7e6cc 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -134,8 +134,8 @@ import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.mobile.MobileAppService; import org.thingsboard.server.dao.model.ModelConstants; -import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; import org.thingsboard.server.dao.oauth2.OAuth2ClientService; +import org.thingsboard.server.dao.oauth2.OAuth2ConfigTemplateService; import org.thingsboard.server.dao.ota.OtaPackageService; import org.thingsboard.server.dao.queue.QueueService; import org.thingsboard.server.dao.relation.RelationService; @@ -172,8 +172,8 @@ import org.thingsboard.server.service.sync.vc.EntitiesVersionControlService; import org.thingsboard.server.service.telemetry.AlarmSubscriptionService; import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; +import java.net.URI; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -918,6 +918,19 @@ public abstract class BaseController { return ResponseEntity.status(status).build(); } + protected ResponseEntity redirectTo(String location) { + URI uri; + try { + uri = URI.create(location); + } catch (IllegalArgumentException e) { + log.error("Failed to create URI from '{}'", location, e); + throw e; + } + return ResponseEntity.status(HttpStatus.SEE_OTHER) + .location(uri) + .build(); + } + protected List getOAuth2ClientIds(UUID[] ids) throws ThingsboardException { if (ids == null) { return Collections.emptyList(); diff --git a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java index e4010713d8..d2586b93e9 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java @@ -195,7 +195,8 @@ public class AuthControllerTest extends AbstractControllerTest { userCredentialsDao.save(tenantId, userCredentials); doGet("/api/noauth/resetPassword?resetToken={resetToken}", this.currentResetPasswordToken) - .andExpect(status().isGone()); + .andExpect(status().isSeeOther()) + .andExpect(header().string(HttpHeaders.LOCATION, "/passwordResetLinkExpired")); JsonNode resetPasswordRequest = JacksonUtil.newObjectNode() .put("resetToken", this.currentResetPasswordToken) .put("password", "wefwefe"); @@ -229,7 +230,8 @@ public class AuthControllerTest extends AbstractControllerTest { userCredentials.setActivateTokenExpTime(System.currentTimeMillis() - 1); userCredentialsDao.save(tenantId, userCredentials); doGet("/api/noauth/activate?activateToken={activateToken}", initialActivationToken) - .andExpect(status().isGone()); + .andExpect(status().isSeeOther()) + .andExpect(header().string(HttpHeaders.LOCATION, "/activationLinkExpired")); doPost("/api/noauth/activate", JacksonUtil.newObjectNode() .put("activateToken", initialActivationToken) .put("password", "wefewe")).andExpect(status().isBadRequest()) From 8233d6c451cace5dd0412b938cd0d26648986575 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Wed, 4 Sep 2024 18:28:02 +0300 Subject: [PATCH 26/80] Include password reset and activation links ttl in the email --- .../server/controller/AuthController.java | 2 +- .../server/controller/UserController.java | 42 +++++-------------- .../entitiy/user/DefaultUserService.java | 31 +++++++++++--- .../service/entitiy/user/TbUserService.java | 5 +++ .../service/mail/DefaultMailService.java | 11 ++--- .../main/resources/templates/activation.ftl | 2 +- .../resources/templates/reset.password.ftl | 2 +- .../server/controller/AbstractWebTest.java | 5 ++- .../server/controller/AuthControllerTest.java | 12 +++--- .../common/data/UserActivationLink.java | 19 +++++++++ .../common/data/security/UserCredentials.java | 7 +++- .../rule/engine/api/MailService.java | 6 +-- 12 files changed, 87 insertions(+), 57 deletions(-) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/UserActivationLink.java diff --git a/application/src/main/java/org/thingsboard/server/controller/AuthController.java b/application/src/main/java/org/thingsboard/server/controller/AuthController.java index a52a80f9f0..17f7930eff 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AuthController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AuthController.java @@ -159,7 +159,7 @@ public class AuthController extends BaseController { String resetUrl = String.format("%s/api/noauth/resetPassword?resetToken=%s", baseUrl, userCredentials.getResetToken()); - mailService.sendResetPasswordEmailAsync(resetUrl, email); + mailService.sendResetPasswordEmailAsync(resetUrl, userCredentials.getResetTokenTtl(), email); } catch (Exception e) { log.warn("Error occurred: {}", e.getMessage()); } diff --git a/application/src/main/java/org/thingsboard/server/controller/UserController.java b/application/src/main/java/org/thingsboard/server/controller/UserController.java index 823129d59b..a71bd4dd38 100644 --- a/application/src/main/java/org/thingsboard/server/controller/UserController.java +++ b/application/src/main/java/org/thingsboard/server/controller/UserController.java @@ -43,6 +43,7 @@ import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.UserActivationLink; import org.thingsboard.server.common.data.UserEmailInfo; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; @@ -85,7 +86,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import static org.thingsboard.server.common.data.query.EntityKeyType.ENTITY_FIELD; import static org.thingsboard.server.controller.ControllerConstants.ALARM_ID_PARAM_DESCRIPTION; @@ -119,7 +119,6 @@ public class UserController extends BaseController { public static final String USER_ID = "userId"; public static final String PATHS = "paths"; public static final String YOU_DON_T_HAVE_PERMISSION_TO_PERFORM_THIS_OPERATION = "You don't have permission to perform this operation!"; - public static final String ACTIVATE_URL_PATTERN = "%s/api/noauth/activate?activateToken=%s"; public static final String MOBILE_TOKEN_HEADER = "X-Mobile-Token"; @Value("${security.user_token_access_enabled}") @@ -226,11 +225,12 @@ public class UserController extends BaseController { @Parameter(description = "Email of the user", required = true) @RequestParam(value = "email") String email, HttpServletRequest request) throws ThingsboardException { - User user = checkNotNull(userService.findUserByEmail(getCurrentUser().getTenantId(), email)); - accessControlService.checkPermission(getCurrentUser(), Resource.USER, Operation.READ, user.getId(), user); + SecurityUser securityUser = getCurrentUser(); + User user = checkNotNull(userService.findUserByEmail(securityUser.getTenantId(), email)); + accessControlService.checkPermission(securityUser, Resource.USER, Operation.READ, user.getId(), user); - ActivationLink activationLink = getActivationLink(user.getId(), request); - mailService.sendActivationEmail(activationLink.value(), email); + UserActivationLink activationLink = tbUserService.getActivationLink(securityUser.getTenantId(), securityUser.getCustomerId(), user.getId(), request); + mailService.sendActivationEmail(activationLink.value(), activationLink.ttlMs(), email); } @ApiOperation(value = "Get activation link (getActivationLink)", @@ -250,13 +250,14 @@ public class UserController extends BaseController { "The base url for activation link is configurable in the general settings of system administrator. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')") @GetMapping(value = "/user/{userId}/activationLinkInfo") - public ActivationLink getActivationLinkInfo(@Parameter(description = USER_ID_PARAM_DESCRIPTION) - @PathVariable(USER_ID) String strUserId, - HttpServletRequest request) throws ThingsboardException { + public UserActivationLink getActivationLinkInfo(@Parameter(description = USER_ID_PARAM_DESCRIPTION) + @PathVariable(USER_ID) String strUserId, + HttpServletRequest request) throws ThingsboardException { checkParameter(USER_ID, strUserId); UserId userId = new UserId(toUUID(strUserId)); checkUserId(userId, Operation.READ); - return getActivationLink(userId, request); + SecurityUser securityUser = getCurrentUser(); + return tbUserService.getActivationLink(securityUser.getTenantId(), securityUser.getCustomerId(), userId, request); } @ApiOperation(value = "Delete User (deleteUser)", @@ -598,31 +599,10 @@ public class UserController extends BaseController { userService.removeMobileSession(user.getTenantId(), mobileToken); } - private ActivationLink getActivationLink(UserId userId, HttpServletRequest request) throws ThingsboardException { - TenantId tenantId = getTenantId(); - UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, userId); - if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { - long ttl = userCredentials.getActivationTokenTtl(); - if (ttl < TimeUnit.MINUTES.toMillis(15)) { // renew link if less than 15 minutes before expiration - userCredentials = userService.generateUserActivationToken(userCredentials); - userCredentials = userService.saveUserCredentials(tenantId, userCredentials); - ttl = userCredentials.getActivationTokenTtl(); - log.debug("[{}][{}] Regenerated expired user activation token", tenantId, userId); - } - String baseUrl = systemSecurityService.getBaseUrl(tenantId, getCurrentUser().getCustomerId(), request); - String link = String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken()); - return new ActivationLink(link, ttl); - } else { - throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); - } - } - private void checkNotReserved(String strType, UserSettingsType type) throws ThingsboardException { if (type.isReserved()) { throw new ThingsboardException("Settings with type: " + strType + " are reserved for internal use!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); } } - record ActivationLink(String value, long ttlMs) {} - } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java index 3b86f9acfe..ad4b7c097e 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/user/DefaultUserService.java @@ -22,7 +22,9 @@ import org.springframework.stereotype.Service; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.UserActivationLink; import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -33,7 +35,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.entitiy.AbstractTbEntityService; import org.thingsboard.server.service.security.system.SystemSecurityService; -import static org.thingsboard.server.controller.UserController.ACTIVATE_URL_PATTERN; +import java.util.concurrent.TimeUnit; @Service @TbCoreComponent @@ -53,12 +55,9 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse boolean sendEmail = tbUser.getId() == null && sendActivationMail; User savedUser = checkNotNull(userService.saveUser(tenantId, tbUser)); if (sendEmail) { - UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, savedUser.getId()); - String baseUrl = systemSecurityService.getBaseUrl(tenantId, customerId, request); - String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl, userCredentials.getActivateToken()); - String email = savedUser.getEmail(); + UserActivationLink activationLink = getActivationLink(tenantId, customerId, savedUser.getId(), request); try { - mailService.sendActivationEmail(activateUrl, email); + mailService.sendActivationEmail(activationLink.value(), activationLink.ttlMs(), savedUser.getEmail()); } catch (ThingsboardException e) { userService.deleteUser(tenantId, savedUser); throw e; @@ -86,4 +85,24 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse throw e; } } + + @Override + public UserActivationLink getActivationLink(TenantId tenantId, CustomerId customerId, UserId userId, HttpServletRequest request) throws ThingsboardException { + UserCredentials userCredentials = userService.findUserCredentialsByUserId(tenantId, userId); + if (!userCredentials.isEnabled() && userCredentials.getActivateToken() != null) { + long ttl = userCredentials.getActivationTokenTtl(); + if (ttl < TimeUnit.MINUTES.toMillis(15)) { // renew link if less than 15 minutes before expiration + userCredentials = userService.generateUserActivationToken(userCredentials); + userCredentials = userService.saveUserCredentials(tenantId, userCredentials); + ttl = userCredentials.getActivationTokenTtl(); + log.debug("[{}][{}] Regenerated expired user activation token", tenantId, userId); + } + String baseUrl = systemSecurityService.getBaseUrl(tenantId, customerId, request); + String link = baseUrl + "/api/noauth/activate?activateToken=" + userCredentials.getActivateToken(); + return new UserActivationLink(link, ttl); + } else { + throw new ThingsboardException("User is already activated!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } + } + } diff --git a/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java b/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java index 388db9df40..e7689692a4 100644 --- a/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java +++ b/application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java @@ -16,14 +16,19 @@ package org.thingsboard.server.service.entitiy.user; import jakarta.servlet.http.HttpServletRequest; +import org.thingsboard.server.common.data.UserActivationLink; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.id.UserId; public interface TbUserService { User save(TenantId tenantId, CustomerId customerId, User tbUser, boolean sendActivationMail, HttpServletRequest request, User user) throws ThingsboardException; void delete(TenantId tenantId, CustomerId customerId, User user, User responsibleUser) throws ThingsboardException; + + UserActivationLink getActivationLink(TenantId tenantId, CustomerId customerId, UserId userId, HttpServletRequest request) throws ThingsboardException; + } diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java index 3577683729..1603720450 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java @@ -160,12 +160,12 @@ public class DefaultMailService implements MailService { } @Override - public void sendActivationEmail(String activationLink, String email) throws ThingsboardException { - + public void sendActivationEmail(String activationLink, long ttlMs, String email) throws ThingsboardException { String subject = messages.getMessage("activation.subject", null, Locale.US); Map model = new HashMap<>(); model.put("activationLink", activationLink); + model.put("activationLinkTtlInHours", (int) Math.ceil(ttlMs / 3600000.0)); model.put(TARGET_EMAIL, email); String message = mergeTemplateIntoString("activation.ftl", model); @@ -188,12 +188,13 @@ public class DefaultMailService implements MailService { } @Override - public void sendResetPasswordEmail(String passwordResetLink, String email) throws ThingsboardException { + public void sendResetPasswordEmail(String passwordResetLink, long ttlMs, String email) throws ThingsboardException { String subject = messages.getMessage("reset.password.subject", null, Locale.US); Map model = new HashMap<>(); model.put("passwordResetLink", passwordResetLink); + model.put("passwordResetLinkTtlInHours", (int) Math.ceil(ttlMs / 3600000.0)); model.put(TARGET_EMAIL, email); String message = mergeTemplateIntoString("reset.password.ftl", model); @@ -202,10 +203,10 @@ public class DefaultMailService implements MailService { } @Override - public void sendResetPasswordEmailAsync(String passwordResetLink, String email) { + public void sendResetPasswordEmailAsync(String passwordResetLink, long ttlMs, String email) { passwordResetExecutorService.execute(() -> { try { - this.sendResetPasswordEmail(passwordResetLink, email); + this.sendResetPasswordEmail(passwordResetLink, ttlMs, email); } catch (Exception e) { log.error("Error occurred: {} ", e.getMessage()); } diff --git a/application/src/main/resources/templates/activation.ftl b/application/src/main/resources/templates/activation.ftl index ce51930521..d5c148a56b 100644 --- a/application/src/main/resources/templates/activation.ftl +++ b/application/src/main/resources/templates/activation.ftl @@ -88,7 +88,7 @@ background-color: #f6f6f6; - To confirm your email address and choose a password, just click the button below. + To confirm your email address and choose a password, just click the button below. The link will expire in ${activationLinkTtlInHours} hours. diff --git a/application/src/main/resources/templates/reset.password.ftl b/application/src/main/resources/templates/reset.password.ftl index 3f36c922f0..6b2fa5e8bf 100644 --- a/application/src/main/resources/templates/reset.password.ftl +++ b/application/src/main/resources/templates/reset.password.ftl @@ -93,7 +93,7 @@ background-color: #f6f6f6; - Click below in order to proceed password reset procedure. + Click below in order to proceed password reset procedure. The link will expire in ${passwordResetLinkTtlInHours} hours. diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java index eba04e7b5e..af20c71e5b 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java @@ -145,6 +145,7 @@ import java.util.function.Consumer; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; @@ -340,7 +341,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { currentActivateToken = activationLink.split("=")[1]; return null; } - }).when(mailService).sendActivationEmail(anyString(), anyString()); + }).when(mailService).sendActivationEmail(anyString(), anyLong(), anyString()); Mockito.doAnswer(new Answer() { public Void answer(InvocationOnMock invocation) { @@ -349,7 +350,7 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest { currentResetPasswordToken = passwordResetLink.split("=")[1]; return null; } - }).when(mailService).sendResetPasswordEmailAsync(anyString(), anyString()); + }).when(mailService).sendResetPasswordEmailAsync(anyString(), anyLong(), anyString()); } @After diff --git a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java index d2586b93e9..817ded33e7 100644 --- a/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/AuthControllerTest.java @@ -26,10 +26,10 @@ import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils; import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.User; +import org.thingsboard.server.common.data.UserActivationLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.UserCredentials; import org.thingsboard.server.common.data.security.model.SecuritySettings; -import org.thingsboard.server.controller.UserController.ActivationLink; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.dao.user.UserCredentialsDao; import org.thingsboard.server.service.security.auth.rest.LoginRequest; @@ -222,7 +222,7 @@ public class AuthControllerTest extends AbstractControllerTest { assertThat(userCredentials.getActivateTokenExpTime()).isCloseTo(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(ttl), Offset.offset(120000L)); String initialActivationLink = getActivationLink(user); String initialActivationToken = StringUtils.substringAfterLast(initialActivationLink, "activateToken="); - ActivationLink activationLinkInfo = getActivationLinkInfo(user); + UserActivationLink activationLinkInfo = getActivationLinkInfo(user); assertThat(TimeUnit.MILLISECONDS.toHours(activationLinkInfo.ttlMs())).isCloseTo(ttl, within(1L)); assertThat(activationLinkInfo.value()).isEqualTo(initialActivationLink); @@ -238,7 +238,7 @@ public class AuthControllerTest extends AbstractControllerTest { .andExpect(jsonPath("$.message", is("Activation token expired"))); // checking that activation link is regenerated when requested - ActivationLink regeneratedActivationLink = getActivationLinkInfo(user); + UserActivationLink regeneratedActivationLink = getActivationLinkInfo(user); assertThat(regeneratedActivationLink.value()).isNotEqualTo(initialActivationLink); assertThat(TimeUnit.MILLISECONDS.toHours(regeneratedActivationLink.ttlMs())).isCloseTo(ttl, within(1L)); @@ -252,7 +252,7 @@ public class AuthControllerTest extends AbstractControllerTest { userCredentials.setActivateTokenExpTime(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10)); userCredentialsDao.save(tenantId, userCredentials); - ActivationLink newActivationLink = getActivationLinkInfo(user); + UserActivationLink newActivationLink = getActivationLinkInfo(user); assertThat(newActivationLink.value()).isNotEqualTo(regeneratedActivationLink.value()); assertThat(TimeUnit.MILLISECONDS.toHours(newActivationLink.ttlMs())).isCloseTo(ttl, within(1L)); String newActivationToken = StringUtils.substringAfterLast(newActivationLink.value(), "activateToken="); @@ -281,8 +281,8 @@ public class AuthControllerTest extends AbstractControllerTest { return doGet("/api/user/" + user.getId() + "/activationLink", String.class); } - private ActivationLink getActivationLinkInfo(User user) throws Exception { - return doGet("/api/user/" + user.getId() + "/activationLinkInfo", ActivationLink.class); + private UserActivationLink getActivationLinkInfo(User user) throws Exception { + return doGet("/api/user/" + user.getId() + "/activationLinkInfo", UserActivationLink.class); } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/UserActivationLink.java b/common/data/src/main/java/org/thingsboard/server/common/data/UserActivationLink.java new file mode 100644 index 0000000000..f532a9b066 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/UserActivationLink.java @@ -0,0 +1,19 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.common.data; + +public record UserActivationLink(String value, long ttlMs) { +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java b/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java index f6e23b9e1a..1104ae2949 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/security/UserCredentials.java @@ -62,7 +62,12 @@ public class UserCredentials extends BaseDataWithAdditionalInfo resetTokenExpTime; + return getResetTokenTtl() == 0; + } + + @JsonIgnore + public long getResetTokenTtl() { + return resetTokenExpTime != null ? Math.max(resetTokenExpTime - System.currentTimeMillis(), 0) : 0; } } diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java index ecaf7ef3f9..043181a710 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/MailService.java @@ -32,13 +32,13 @@ public interface MailService { void sendTestMail(JsonNode config, String email) throws ThingsboardException; - void sendActivationEmail(String activationLink, String email) throws ThingsboardException; + void sendActivationEmail(String activationLink, long ttlMs, String email) throws ThingsboardException; void sendAccountActivatedEmail(String loginLink, String email) throws ThingsboardException; - void sendResetPasswordEmail(String passwordResetLink, String email) throws ThingsboardException; + void sendResetPasswordEmail(String passwordResetLink, long ttlMs, String email) throws ThingsboardException; - void sendResetPasswordEmailAsync(String passwordResetLink, String email); + void sendResetPasswordEmailAsync(String passwordResetLink, long ttlMs, String email); void sendPasswordWasResetEmail(String loginLink, String email) throws ThingsboardException; From 620322e3f64ca4a0e4056901bbcdd9ff35282399 Mon Sep 17 00:00:00 2001 From: rusikv Date: Thu, 5 Sep 2024 12:02:42 +0300 Subject: [PATCH 27/80] UI: expiration message for activation link dialog, expired activation or password reset links redirect to message view about expiration --- ui-ngx/src/app/core/http/user.service.ts | 6 ++- .../activation-link-dialog.component.html | 2 +- .../user/activation-link-dialog.component.ts | 18 +++---- .../pages/user/add-user-dialog.component.ts | 8 ++-- .../pages/user/users-table-config.resolver.ts | 6 +-- .../app/modules/login/login-routing.module.ts | 20 ++++++++ ui-ngx/src/app/modules/login/login.module.ts | 4 +- .../pages/login/link-expired.component.html | 40 ++++++++++++++++ .../pages/login/link-expired.component.scss | 32 +++++++++++++ .../pages/login/link-expired.component.ts | 47 +++++++++++++++++++ ui-ngx/src/app/shared/models/user.model.ts | 5 ++ .../assets/locale/locale.constant-en_US.json | 8 +++- 12 files changed, 176 insertions(+), 20 deletions(-) create mode 100644 ui-ngx/src/app/modules/login/pages/login/link-expired.component.html create mode 100644 ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss create mode 100644 ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts diff --git a/ui-ngx/src/app/core/http/user.service.ts b/ui-ngx/src/app/core/http/user.service.ts index 1d5ce28998..695bae3cc1 100644 --- a/ui-ngx/src/app/core/http/user.service.ts +++ b/ui-ngx/src/app/core/http/user.service.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils'; -import { User, UserEmailInfo } from '@shared/models/user.model'; +import { ActivationLinkInfo, User, UserEmailInfo } from '@shared/models/user.model'; import { Observable } from 'rxjs'; import { HttpClient, HttpParams } from '@angular/common/http'; import { PageLink } from '@shared/models/page/page-link'; @@ -77,6 +77,10 @@ export class UserService { {...{responseType: 'text'}, ...defaultHttpOptionsFromConfig(config)}); } + public getActivationLinkInfo(userId: string, config?: RequestConfig): Observable { + return this.http.get(`/api/user/${userId}/activationLinkInfo`, defaultHttpOptionsFromConfig(config)); + } + public sendActivationEmail(email: string, config?: RequestConfig) { const encodeEmail = encodeURIComponent(email); return this.http.post(`/api/user/sendActivationMail?email=${encodeEmail}`, null, defaultHttpOptionsFromConfig(config)); diff --git a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html index cabb688525..d03b50418d 100644 --- a/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/user/activation-link-dialog.component.html @@ -30,7 +30,7 @@
- +
{{ activationLink }}
+ + +
diff --git a/ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss new file mode 100644 index 0000000000..323437e66b --- /dev/null +++ b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.scss @@ -0,0 +1,32 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@import '../../../../../scss/constants'; + +:host { + display: flex; + flex: 1 1 0; + .tb-expired-link-content { + background-color: #eee; + .tb-expired-link-card { + letter-spacing: 0.15px; + line-height: 24px; + padding: 24px; + @media #{$mat-gt-xs} { + width: 486px !important; + } + } + } +} diff --git a/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts new file mode 100644 index 0000000000..d394e426dd --- /dev/null +++ b/ui-ngx/src/app/modules/login/pages/login/link-expired.component.ts @@ -0,0 +1,47 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { PageComponent } from '@shared/components/page.component'; +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + selector: 'tb-link-expired', + templateUrl: './link-expired.component.html', + styleUrls: ['./link-expired.component.scss'] +}) +export class LinkExpiredComponent extends PageComponent { + + isPasswordLinkExpired: boolean; + title: string; + message: string; + + constructor(protected store: Store, + private route: ActivatedRoute, + private router: Router) { + super(store); + this.isPasswordLinkExpired = this.route.snapshot.data.passwordLinkExpired; + this.title = this.isPasswordLinkExpired ? 'login.reset-password-link-expired' : 'login.activation-link-expired'; + this.message = this.isPasswordLinkExpired ? 'login.reset-password-link-expired-message' : + 'login.activation-link-expired-message'; + } + + navigateToLoginPage() { + this.router.navigateByUrl('login'); + } +} diff --git a/ui-ngx/src/app/shared/models/user.model.ts b/ui-ngx/src/app/shared/models/user.model.ts index 5b2cdec08b..a17cf040a8 100644 --- a/ui-ngx/src/app/shared/models/user.model.ts +++ b/ui-ngx/src/app/shared/models/user.model.ts @@ -44,6 +44,11 @@ export const activationMethodTranslations = new Map( ] ); +export interface ActivationLinkInfo { + value: string; + ttlMs: number; +} + export interface AuthUser { sub: string; scopes: string[]; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 24d2ab5511..204e44f7be 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4009,7 +4009,11 @@ "email-auth-description": "A security code has been sent to your email address at {{contact}}.", "email-auth-placeholder": "Email code", "backup-code-auth-description": "Please enter one of your backup codes.", - "backup-code-auth-placeholder": "Backup code" + "backup-code-auth-placeholder": "Backup code", + "activation-link-expired": "Activation link has expired", + "activation-link-expired-message": "The link to activate your profile has expired. You can return to the login page to receive a new email.", + "reset-password-link-expired": "Password reset link has expired", + "reset-password-link-expired-message": "The link to reset your password has expired. You can return to the login page to receive a new email." }, "markdown": { "edit": "Edit", @@ -5629,7 +5633,7 @@ "display-activation-link": "Display activation link", "send-activation-mail": "Send activation mail", "activation-link": "User activation link", - "activation-link-text": "In order to activate user use the following activation link :", + "activation-link-text": "In order to activate user use the following activation link (expires in {{activationLinkTtl}}) :", "copy-activation-link": "Copy activation link", "activation-link-copied-message": "User activation link has been copied to clipboard", "details": "Details", From 7c442b000af912499df7b9f54ec9699bdc2c2690 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Fri, 6 Sep 2024 15:26:13 +0300 Subject: [PATCH 28/80] UI: Minor inmprovement for SCADA system --- .../widget/lib/scada/scada-symbol.models.ts | 9 +- .../home/pages/admin/admin-routing.module.ts | 3 +- ...scada-symbol-property-panel.component.html | 1 + .../save-widget-type-as-dialog.component.html | 1 + .../pages/widget/widget-library.module.ts | 4 +- .../widgets-bundle-dialog.component.html | 53 +++++++++++ .../widgets-bundle-dialog.component.scss | 22 +++++ .../widget/widgets-bundle-dialog.component.ts | 95 +++++++++++++++++++ .../widget/widgets-bundle.component.html | 2 +- .../pages/widget/widgets-bundle.component.ts | 9 +- .../image/image-gallery.component.ts | 16 +++- .../widgets-bundle-select.component.html | 7 +- .../widgets-bundle-select.component.ts | 57 ++++++++++- .../app/shared/models/widgets-bundle.model.ts | 3 +- .../assets/locale/locale.constant-en_US.json | 3 +- 15 files changed, 264 insertions(+), 21 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.html create mode 100644 ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.scss create mode 100644 ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts index 3c4e32abf7..bb6cc17869 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts @@ -191,10 +191,10 @@ export interface ScadaSymbolMetadata { properties: ScadaSymbolProperty[]; } -export const emptyMetadata = (): ScadaSymbolMetadata => ({ +export const emptyMetadata = (width?: number, height?: number): ScadaSymbolMetadata => ({ title: '', - widgetSizeX: 3, - widgetSizeY: 3, + widgetSizeX: width ? width/100 : 3, + widgetSizeY: height ? height/100 : 3, tags: [], behavior: [], properties: [] @@ -255,7 +255,8 @@ const parseScadaSymbolMetadataFromDom = (svgDoc: Document): ScadaSymbolMetadata if (elements.length) { return JSON.parse(elements[0].textContent); } else { - return emptyMetadata(); + const viewBox = svgDoc.getElementsByTagName('svg')[0].viewBox.baseVal; + return emptyMetadata(viewBox.width, viewBox.height); } } catch (_e) { console.error(_e); diff --git a/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts b/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts index 7d3e9983f8..b4a4d01326 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts @@ -114,7 +114,8 @@ const routes: Routes = [ data: { auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN], title: 'scada.symbols', - imageSubType: ResourceSubType.SCADA_SYMBOL + imageSubType: ResourceSubType.SCADA_SYMBOL, + editOnRowClick: true } }, { diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html index 9fd461c229..15322b38d4 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html @@ -136,6 +136,7 @@
scada.property.disable-on-property
+ {{ prop }} diff --git a/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.html b/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.html index 8d0f6bd6f5..804730dbfe 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.html +++ b/ui-ngx/src/app/modules/home/pages/widget/save-widget-type-as-dialog.component.html @@ -39,6 +39,7 @@
diff --git a/ui-ngx/src/app/modules/home/pages/widget/widget-library.module.ts b/ui-ngx/src/app/modules/home/pages/widget/widget-library.module.ts index 1ee25529b0..80438b4f4d 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widget-library.module.ts +++ b/ui-ngx/src/app/modules/home/pages/widget/widget-library.module.ts @@ -28,6 +28,7 @@ import { WidgetTypeComponent } from '@home/pages/widget/widget-type.component'; import { WidgetTypeTabsComponent } from '@home/pages/widget/widget-type-tabs.component'; import { WidgetsBundleWidgetsComponent } from '@home/pages/widget/widgets-bundle-widgets.component'; import { WidgetTypeAutocompleteComponent } from '@home/pages/widget/widget-type-autocomplete.component'; +import { WidgetsBundleDialogComponent } from '@home/pages/widget/widgets-bundle-dialog.component'; @NgModule({ declarations: [ @@ -39,7 +40,8 @@ import { WidgetTypeAutocompleteComponent } from '@home/pages/widget/widget-type- SelectWidgetTypeDialogComponent, SaveWidgetTypeAsDialogComponent, WidgetTypeTabsComponent, - WidgetsBundleTabsComponent + WidgetsBundleTabsComponent, + WidgetsBundleDialogComponent ], imports: [ CommonModule, diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.html b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.html new file mode 100644 index 0000000000..592be51486 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.html @@ -0,0 +1,53 @@ + +
+ +

widgets-bundle.add

+ + +
+ + +
+
+ + +
+
+ + +
+
diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.scss new file mode 100644 index 0000000000..0556c6bd25 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.scss @@ -0,0 +1,22 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:host ::ng-deep { + tb-widgets-bundle { + .mat-padding { + padding: 0; + } + } +} diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts new file mode 100644 index 0000000000..1f0c963af5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle-dialog.component.ts @@ -0,0 +1,95 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { + AfterViewInit, + Component, + ComponentFactoryResolver, + Inject, + Injector, + SkipSelf, + ViewChild +} from '@angular/core'; +import { ErrorStateMatcher } from '@angular/material/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { FormGroupDirective, NgForm, UntypedFormControl } from '@angular/forms'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { Router } from '@angular/router'; +import { TenantProfileService } from '@core/http/tenant-profile.service'; +import { WidgetsBundle } from '@shared/models/widgets-bundle.model'; +import { WidgetsBundleComponent } from '@home/pages/widget/widgets-bundle.component'; +import { WidgetService } from '@core/http/widget.service'; + +export interface WidgetsBundleDialogData { + widgetsBundle: WidgetsBundle; +} + +@Component({ + selector: 'tb-widgets-bundle-dialog', + templateUrl: './widgets-bundle-dialog.component.html', + providers: [{provide: ErrorStateMatcher, useExisting: WidgetsBundleDialogComponent}], + styleUrls: ['widgets-bundle-dialog.component.scss'] +}) +export class WidgetsBundleDialogComponent extends + DialogComponent implements ErrorStateMatcher, AfterViewInit { + + widgetsBundle: WidgetsBundle; + + submitted = false; + + @ViewChild('widgetsBundleComponent', {static: true}) widgetsBundleComponent: WidgetsBundleComponent; + + constructor(protected store: Store, + protected router: Router, + @Inject(MAT_DIALOG_DATA) public data: WidgetsBundleDialogData, + public dialogRef: MatDialogRef, + private componentFactoryResolver: ComponentFactoryResolver, + private injector: Injector, + @SkipSelf() private errorStateMatcher: ErrorStateMatcher, + private widgetsService: WidgetService) { + super(store, router, dialogRef); + this.widgetsBundle = this.data.widgetsBundle; + } + + ngAfterViewInit(): void { + setTimeout(() => { + this.widgetsBundleComponent.entityForm.markAsDirty(); + }, 0); + } + + isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean { + const originalErrorState = this.errorStateMatcher.isErrorState(control, form); + const customErrorState = !!(control && control.invalid && this.submitted); + return originalErrorState || customErrorState; + } + + cancel(): void { + this.dialogRef.close(null); + } + + save(): void { + this.submitted = true; + if (this.widgetsBundleComponent.entityForm.valid) { + this.widgetsBundle = {...this.widgetsBundle, ...this.widgetsBundleComponent.entityFormValue()}; + this.widgetsService.saveWidgetsBundle(this.widgetsBundle).subscribe((widgetBundle) => { + this.dialogRef.close(widgetBundle); + }); + } + } + +} diff --git a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html index f95d085688..df66eee579 100644 --- a/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html +++ b/ui-ngx/src/app/modules/home/pages/widget/widgets-bundle.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+
dashboard.mobile-row-height
- + - - warning - px
From f9a64731b30c430367d4f8a7b44cdde176687cb2 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 6 Sep 2024 19:37:27 +0300 Subject: [PATCH 33/80] Fixed default credentials for created Gateway and refactored gateway basic config --- .../gateway-basic-configuration.component.ts | 426 +++++++++++------- .../gateway-configuration.component.ts | 6 +- 2 files changed, 257 insertions(+), 175 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/basic/gateway-basic-configuration.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/basic/gateway-basic-configuration.component.ts index 4b47dd15c4..e63a60372e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/basic/gateway-basic-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/basic/gateway-basic-configuration.component.ts @@ -43,7 +43,7 @@ import { } from '@home/components/widget/lib/gateway/gateway-remote-configuration-dialog'; import { DeviceService } from '@core/http/device.service'; import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; +import { take, takeUntil } from 'rxjs/operators'; import { DeviceCredentials, DeviceCredentialsType } from '@shared/models/device.models'; import { GatewayLogLevel, @@ -61,7 +61,9 @@ import { CommonModule } from '@angular/common'; import { coerceBoolean } from '@shared/decorators/coercion'; import { GatewayConfigCommand, - GatewayConfigValue, LogConfig + GatewayConfigSecurity, + GatewayConfigValue, + LogConfig } from '@home/components/widget/lib/gateway/configuration/models/gateway-configuration.models'; @Component({ @@ -99,13 +101,14 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal initialCredentialsUpdated = new EventEmitter(); StorageTypes = StorageTypes; - storageTypes = Object.values(StorageTypes) as StorageTypes[]; + storageTypes = Object.values(StorageTypes); storageTypesTranslationMap = StorageTypesTranslationMap; logSavingPeriods = LogSavingPeriodTranslations; localLogsConfigs = Object.keys(LocalLogsConfigs) as LocalLogsConfigs[]; localLogsConfigTranslateMap = LocalLogsConfigTranslateMap; securityTypes = GecurityTypesTranslationsMap; gatewayLogLevel = Object.values(GatewayLogLevel); + logSelector: FormControl; basicFormGroup: FormGroup; @@ -119,6 +122,7 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal private cd: ChangeDetectorRef, private dialog: MatDialog) { this.initBasicFormGroup(); + this.observeFormChanges(); this.basicFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) .subscribe(value => { @@ -142,14 +146,12 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal writeValue(basicConfig: GatewayConfigValue): void { this.basicFormGroup.patchValue(basicConfig, {emitEvent: false}); - if (basicConfig?.thingsboard?.security) { - this.checkAndFetchCredentials(basicConfig.thingsboard.security); - } + this.checkAndFetchCredentials(basicConfig?.thingsboard?.security ?? {} as GatewayConfigSecurity); if (basicConfig?.grpc) { this.toggleRpcFields(basicConfig.grpc.enabled); } - const commands = basicConfig?.thingsboard?.statistics?.commands || []; - commands.forEach(command => this.addCommand(command, false)); + const commands = basicConfig?.thingsboard?.statistics?.commands ?? []; + commands.forEach((command: GatewayConfigCommand) => this.addCommand(command, false)); } validate(): ValidationErrors | null { @@ -251,7 +253,7 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal data: { gatewayName: gateway.name } - }).afterClosed().subscribe( + }).afterClosed().pipe(take(1)).subscribe( (res) => { if (!res) { this.basicFormGroup.get('thingsboard.remoteConfiguration').setValue(true, {emitEvent: false}); @@ -273,214 +275,294 @@ export class GatewayBasicConfigurationComponent implements OnDestroy, ControlVal this.commandFormArray().push(commandFormGroup, { emitEvent }); } - private initBasicFormGroup(): void { this.basicFormGroup = this.fb.group({ - thingsboard: this.fb.group({ - host: [window.location.hostname, [Validators.required, Validators.pattern(/^[^\s]+$/)]], - port: [1883, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], - remoteShell: [false, []], - remoteConfiguration: [true, []], - checkConnectorsConfigurationInSeconds: [60, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - statistics: this.fb.group({ - enable: [true, []], - statsSendPeriodInSeconds: [3600, [Validators.required, Validators.min(60), Validators.pattern(/^-?[0-9]+$/)]], - commands: this.fb.array([], []) - }), - maxPayloadSizeBytes: [8196, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], - minPackSendDelayMS: [50, [Validators.required, Validators.min(10), Validators.pattern(/^-?[0-9]+$/)]], - minPackSizeToSend: [500, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], - handleDeviceRenaming: [true, []], - checkingDeviceActivity: this.fb.group({ - checkDeviceInactivity: [false, []], - inactivityTimeoutSeconds: [200, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - inactivityCheckPeriodSeconds: [500, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]] - }), - security: this.fb.group({ - type: [SecurityTypes.ACCESS_TOKEN, [Validators.required]], - accessToken: [null, [Validators.required, Validators.pattern(/^[^.\s]+$/)]], - clientId: [null, [Validators.pattern(/^[^.\s]+$/)]], - username: [null, [Validators.pattern(/^[^.\s]+$/)]], - password: [null, [Validators.pattern(/^[^.\s]+$/)]], - caCert: [null, []], - cert: [null, []], - privateKey: [null, []], - }), - qos: [1, [Validators.min(0), Validators.max(1), Validators.required, Validators.pattern(/^[^.\s]+$/)]] - }), - storage: this.fb.group({ - type: [StorageTypes.MEMORY, [Validators.required]], - read_records_count: [ - 100, [Validators.min(1), - Validators.pattern(/^-?[0-9]+$/), Validators.required, Validators.pattern(/^[^.\s]+$/)] - ], - max_records_count: [ - 100000, - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required, Validators.pattern(/^[^.\s]+$/)] - ], - data_folder_path: ['./data/', [Validators.required]], - max_file_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - max_read_records_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - max_records_per_file: [10000, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - data_file_path: ['./data/data.db', [Validators.required]], - messages_ttl_check_in_hours: [1, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - messages_ttl_in_days: [7, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + thingsboard: this.initThingsboardFormGroup(), + storage: this.initStorageFormGroup(), + grpc: this.initGrpcFormGroup(), + connectors: this.fb.array([]), + logs: this.initLogsFormGroup(), + }); + } + private initThingsboardFormGroup(): FormGroup { + return this.fb.group({ + host: [window.location.hostname, [Validators.required, Validators.pattern(/^[^\s]+$/)]], + port: [1883, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], + remoteShell: [false], + remoteConfiguration: [true], + checkConnectorsConfigurationInSeconds: [60, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + statistics: this.fb.group({ + enable: [true], + statsSendPeriodInSeconds: [3600, [Validators.required, Validators.min(60), Validators.pattern(/^-?[0-9]+$/)]], + commands: this.fb.array([]) }), - grpc: this.fb.group({ - enabled: [false, []], - serverPort: [9595, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], - keepAliveTimeMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - keepAliveTimeoutMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - keepalivePermitWithoutCalls: [true, []], - maxPingsWithoutData: [0, [Validators.required, Validators.min(0), Validators.pattern(/^-?[0-9]+$/)]], - minTimeBetweenPingsMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], - minPingIntervalWithoutDataMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + maxPayloadSizeBytes: [8196, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], + minPackSendDelayMS: [50, [Validators.required, Validators.min(10), Validators.pattern(/^-?[0-9]+$/)]], + minPackSizeToSend: [500, [Validators.required, Validators.min(100), Validators.pattern(/^-?[0-9]+$/)]], + handleDeviceRenaming: [true], + checkingDeviceActivity: this.initCheckingDeviceActivityFormGroup(), + security: this.initSecurityFormGroup(), + qos: [1, [Validators.required, Validators.min(0), Validators.max(1), Validators.pattern(/^[^.\s]+$/)]] + }); + } + + private initStorageFormGroup(): FormGroup { + return this.fb.group({ + type: [StorageTypes.MEMORY, [Validators.required]], + read_records_count: [100, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + max_records_count: [100000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + data_folder_path: ['./data/', [Validators.required]], + max_file_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + max_read_records_count: [10, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + max_records_per_file: [10000, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + data_file_path: ['./data/data.db', [Validators.required]], + messages_ttl_check_in_hours: [1, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + messages_ttl_in_days: [7, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]] + }); + } + + private initGrpcFormGroup(): FormGroup { + return this.fb.group({ + enabled: [false], + serverPort: [9595, [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern(/^-?[0-9]+$/)]], + keepAliveTimeMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + keepAliveTimeoutMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + keepalivePermitWithoutCalls: [true], + maxPingsWithoutData: [0, [Validators.required, Validators.min(0), Validators.pattern(/^-?[0-9]+$/)]], + minTimeBetweenPingsMs: [10000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + minPingIntervalWithoutDataMs: [5000, [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]] + }); + } + + private initLogsFormGroup(): FormGroup { + return this.fb.group({ + dateFormat: ['%Y-%m-%d %H:%M:%S', [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]], + logFormat: [ + '%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s', + [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)] + ], + type: ['remote', [Validators.required]], + remote: this.fb.group({ + enabled: [false], + logLevel: [GatewayLogLevel.INFO, [Validators.required]] }), - connectors: this.fb.array([]), - logs: this.fb.group({ - dateFormat: ['%Y-%m-%d %H:%M:%S', [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]], - logFormat: ['%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s', - [Validators.required, Validators.pattern(/^[^\s].*[^\s]$/)]], - type: ['remote', [Validators.required]], - remote: this.fb.group({ - enabled: [false], - logLevel: [GatewayLogLevel.INFO, [Validators.required]], - }), - local: this.fb.group({}) - }) + local: this.fb.group({}) + }); + } + + private initCheckingDeviceActivityFormGroup(): FormGroup { + return this.fb.group({ + checkDeviceInactivity: [false], + inactivityTimeoutSeconds: [200, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]], + inactivityCheckPeriodSeconds: [500, [Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]] }); + } - this.basicFormGroup.get('thingsboard.security.password').valueChanges.subscribe(password => { + private initSecurityFormGroup(): FormGroup { + return this.fb.group({ + type: [SecurityTypes.ACCESS_TOKEN, [Validators.required]], + accessToken: [null, [Validators.required, Validators.pattern(/^[^.\s]+$/)]], + clientId: [null, [Validators.pattern(/^[^.\s]+$/)]], + username: [null, [Validators.pattern(/^[^.\s]+$/)]], + password: [null, [Validators.pattern(/^[^.\s]+$/)]], + caCert: [null], + cert: [null], + privateKey: [null] + }); + } + + private observeFormChanges(): void { + this.observeSecurityPasswordChanges(); + this.observeRemoteConfigurationChanges(); + this.observeDeviceActivityChanges(); + this.observeSecurityTypeChanges(); + this.observeStorageTypeChanges(); + } + + private observeSecurityPasswordChanges(): void { + const securityUsername = this.basicFormGroup.get('thingsboard.security.username'); + this.basicFormGroup.get('thingsboard.security.password').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(password => { if (password && password !== '') { - this.basicFormGroup.get('thingsboard.security.username').setValidators([Validators.required]); + securityUsername.setValidators([Validators.required]); } else { - this.basicFormGroup.get('thingsboard.security.username').clearValidators(); + securityUsername.clearValidators(); } - this.basicFormGroup.get('thingsboard.security.username').updateValueAndValidity({emitEvent: false}); + securityUsername.updateValueAndValidity({ emitEvent: false }); }); + } - this.toggleRpcFields(false); - - this.basicFormGroup.get('thingsboard.remoteConfiguration').valueChanges.subscribe(enabled => { + private observeRemoteConfigurationChanges(): void { + this.basicFormGroup.get('thingsboard.remoteConfiguration').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(enabled => { if (!enabled) { this.openConfigurationConfirmDialog(); } }); this.logSelector = this.fb.control(LocalLogsConfigs.service); - - for (const localLogsConfigsKey of Object.keys(LocalLogsConfigs)) { - this.addLocalLogConfig(localLogsConfigsKey, {} as LogConfig); + for (const key of Object.keys(LocalLogsConfigs)) { + this.addLocalLogConfig(key, {} as LogConfig); } + } + private observeDeviceActivityChanges(): void { const checkingDeviceActivityGroup = this.basicFormGroup.get('thingsboard.checkingDeviceActivity') as FormGroup; - checkingDeviceActivityGroup.get('checkDeviceInactivity').valueChanges.subscribe(enabled => { + checkingDeviceActivityGroup.get('checkDeviceInactivity').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(enabled => { checkingDeviceActivityGroup.updateValueAndValidity(); + const validators = [Validators.min(1), Validators.required, Validators.pattern(/^-?[0-9]+$/)]; + if (enabled) { - checkingDeviceActivityGroup.get('inactivityTimeoutSeconds') - .setValidators([Validators.min(1), Validators.required, Validators.pattern(/^-?[0-9]+$/)]); - checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds') - .setValidators([Validators.min(1), Validators.required, Validators.pattern(/^-?[0-9]+$/)]); + checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').setValidators(validators); + checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').setValidators(validators); } else { checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').clearValidators(); checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').clearValidators(); } - checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').updateValueAndValidity({emitEvent: false}); - checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').updateValueAndValidity({emitEvent: false}); + checkingDeviceActivityGroup.get('inactivityTimeoutSeconds').updateValueAndValidity({ emitEvent: false }); + checkingDeviceActivityGroup.get('inactivityCheckPeriodSeconds').updateValueAndValidity({ emitEvent: false }); }); - this.basicFormGroup.get('grpc.enabled').valueChanges.subscribe(value => { + this.basicFormGroup.get('grpc.enabled').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => { this.toggleRpcFields(value); }); + } + private observeSecurityTypeChanges(): void { const securityGroup = this.basicFormGroup.get('thingsboard.security') as FormGroup; - securityGroup.get('type').valueChanges.subscribe(type => { + + securityGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(type => { this.removeAllSecurityValidators(); - if (type === SecurityTypes.ACCESS_TOKEN) { - securityGroup.get('accessToken').addValidators([Validators.required, Validators.pattern(/^[^.\s]+$/)]); - securityGroup.get('accessToken').updateValueAndValidity(); - } else if (type === SecurityTypes.TLS_PRIVATE_KEY) { - securityGroup.get('caCert').addValidators([Validators.required]); - securityGroup.get('caCert').updateValueAndValidity(); - securityGroup.get('privateKey').addValidators([Validators.required]); - securityGroup.get('privateKey').updateValueAndValidity(); - securityGroup.get('cert').addValidators([Validators.required]); - securityGroup.get('cert').updateValueAndValidity(); - } else if (type === SecurityTypes.TLS_ACCESS_TOKEN) { - securityGroup.get('accessToken').addValidators([Validators.required, Validators.pattern(/^[^.\s]+$/)]); - securityGroup.get('accessToken').updateValueAndValidity(); - securityGroup.get('caCert').addValidators([Validators.required]); - securityGroup.get('caCert').updateValueAndValidity(); - } else if (type === SecurityTypes.USERNAME_PASSWORD) { - securityGroup.addValidators([this.atLeastOneRequired(Validators.required, ['clientId', 'username'])]); + + switch (type) { + case SecurityTypes.ACCESS_TOKEN: + this.addAccessTokenValidators(securityGroup); + break; + case SecurityTypes.TLS_PRIVATE_KEY: + this.addTlsPrivateKeyValidators(securityGroup); + break; + case SecurityTypes.TLS_ACCESS_TOKEN: + this.addTlsAccessTokenValidators(securityGroup); + break; + case SecurityTypes.USERNAME_PASSWORD: + securityGroup.addValidators([this.atLeastOneRequired(Validators.required, ['clientId', 'username'])]); + break; } + securityGroup.updateValueAndValidity(); }); - securityGroup.get('caCert').valueChanges.subscribe(() => this.cd.detectChanges()); - securityGroup.get('privateKey').valueChanges.subscribe(() => this.cd.detectChanges()); - securityGroup.get('cert').valueChanges.subscribe(() => this.cd.detectChanges()); + ['caCert', 'privateKey', 'cert'].forEach(field => { + securityGroup.get(field).valueChanges.pipe(takeUntil(this.destroy$)).subscribe(() => this.cd.detectChanges()); + }); + } + private observeStorageTypeChanges(): void { const storageGroup = this.basicFormGroup.get('storage') as FormGroup; - storageGroup.get('type').valueChanges.subscribe(type => { + + storageGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(type => { this.removeAllStorageValidators(); - if (type === StorageTypes.MEMORY) { - storageGroup.get('read_records_count').addValidators( - [Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); - storageGroup.get('max_records_count').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('read_records_count').updateValueAndValidity({emitEvent: false}); - storageGroup.get('max_records_count').updateValueAndValidity({emitEvent: false}); - } else if (type === StorageTypes.FILE) { - storageGroup.get('data_folder_path').addValidators([Validators.required]); - storageGroup.get('max_file_count').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('max_read_records_count').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('max_records_per_file').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('data_folder_path').updateValueAndValidity({emitEvent: false}); - storageGroup.get('max_file_count').updateValueAndValidity({emitEvent: false}); - storageGroup.get('max_read_records_count').updateValueAndValidity({emitEvent: false}); - storageGroup.get('max_records_per_file').updateValueAndValidity({emitEvent: false}); - } else if (type === StorageTypes.SQLITE) { - storageGroup.get('data_file_path').addValidators([Validators.required]); - storageGroup.get('messages_ttl_check_in_hours').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('messages_ttl_in_days').addValidators( - [Validators.min(1), Validators.pattern(/^-?[0-9]+$/), Validators.required]); - storageGroup.get('data_file_path').updateValueAndValidity({emitEvent: false}); - storageGroup.get('messages_ttl_check_in_hours').updateValueAndValidity({emitEvent: false}); - storageGroup.get('messages_ttl_in_days').updateValueAndValidity({emitEvent: false}); + + switch (type) { + case StorageTypes.MEMORY: + this.addMemoryStorageValidators(storageGroup); + break; + case StorageTypes.FILE: + this.addFileStorageValidators(storageGroup); + break; + case StorageTypes.SQLITE: + this.addSqliteStorageValidators(storageGroup); + break; } }); } - private checkAndFetchCredentials(security: any = {}): void { - if (security.type !== SecurityTypes.TLS_PRIVATE_KEY) { - this.deviceService.getDeviceCredentials(this.device.id).subscribe(credentials => { - this.initialCredentialsUpdated.emit(credentials); - if (credentials.credentialsType === DeviceCredentialsType.ACCESS_TOKEN || security.type === SecurityTypes.TLS_ACCESS_TOKEN) { - this.basicFormGroup.get('thingsboard.security.type') - .setValue(security.type === SecurityTypes.TLS_ACCESS_TOKEN - ? SecurityTypes.TLS_ACCESS_TOKEN - : SecurityTypes.ACCESS_TOKEN, {emitEvent: false}); - this.basicFormGroup.get('thingsboard.security.accessToken').setValue(credentials.credentialsId, {emitEvent: false}); - if(security.type === SecurityTypes.TLS_ACCESS_TOKEN) { - this.basicFormGroup.get('thingsboard.security.caCert').setValue(security.caCert, {emitEvent: false}); - } - } else if (credentials.credentialsType === DeviceCredentialsType.MQTT_BASIC) { - const parsedValue = JSON.parse(credentials.credentialsValue); - this.basicFormGroup.get('thingsboard.security.type').setValue(SecurityTypes.USERNAME_PASSWORD, {emitEvent: false}); - this.basicFormGroup.get('thingsboard.security.clientId').setValue(parsedValue.clientId, {emitEvent: false}); - this.basicFormGroup.get('thingsboard.security.username').setValue(parsedValue.userName, {emitEvent: false}); - this.basicFormGroup.get('thingsboard.security.password') - .setValue(parsedValue.password, {emitEvent: false}); - } else if (credentials.credentialsType === DeviceCredentialsType.X509_CERTIFICATE) { - //if sertificate is present set sertificate as present - } - }); + private addAccessTokenValidators(group: FormGroup): void { + group.get('accessToken').addValidators([Validators.required, Validators.pattern(/^[^.\s]+$/)]); + group.get('accessToken').updateValueAndValidity(); + } + + private addTlsPrivateKeyValidators(group: FormGroup): void { + ['caCert', 'privateKey', 'cert'].forEach(field => { + group.get(field).addValidators([Validators.required]); + group.get(field).updateValueAndValidity(); + }); + } + + private addTlsAccessTokenValidators(group: FormGroup): void { + this.addAccessTokenValidators(group); + group.get('caCert').addValidators([Validators.required]); + group.get('caCert').updateValueAndValidity(); + } + + private addMemoryStorageValidators(group: FormGroup): void { + group.get('read_records_count').addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); + group.get('max_records_count').addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); + group.get('read_records_count').updateValueAndValidity({ emitEvent: false }); + group.get('max_records_count').updateValueAndValidity({ emitEvent: false }); + } + + private addFileStorageValidators(group: FormGroup): void { + ['data_folder_path', 'max_file_count', 'max_read_records_count', 'max_records_per_file'].forEach(field => { + group.get(field).addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); + group.get(field).updateValueAndValidity({ emitEvent: false }); + }); + } + + private addSqliteStorageValidators(group: FormGroup): void { + ['data_file_path', 'messages_ttl_check_in_hours', 'messages_ttl_in_days'].forEach(field => { + group.get(field).addValidators([Validators.required, Validators.min(1), Validators.pattern(/^-?[0-9]+$/)]); + group.get(field).updateValueAndValidity({ emitEvent: false }); + }); + } + + private checkAndFetchCredentials(security: GatewayConfigSecurity): void { + if (security.type === SecurityTypes.TLS_PRIVATE_KEY) { + return; + } + + this.deviceService.getDeviceCredentials(this.device.id).pipe(takeUntil(this.destroy$)).subscribe(credentials => { + this.initialCredentialsUpdated.emit(credentials); + this.updateSecurityType(security, credentials); + this.updateCredentials(credentials, security); + }); + } + + private updateSecurityType(security, credentials: DeviceCredentials): void { + const isAccessToken = credentials.credentialsType === DeviceCredentialsType.ACCESS_TOKEN + || security.type === SecurityTypes.TLS_ACCESS_TOKEN; + const securityType = isAccessToken + ? (security.type === SecurityTypes.TLS_ACCESS_TOKEN ? SecurityTypes.TLS_ACCESS_TOKEN : SecurityTypes.ACCESS_TOKEN) + : (credentials.credentialsType === DeviceCredentialsType.MQTT_BASIC ? SecurityTypes.USERNAME_PASSWORD : null); + + if (securityType) { + this.basicFormGroup.get('thingsboard.security.type').setValue(securityType, { emitEvent: false }); } } + + private updateCredentials(credentials: DeviceCredentials, security: GatewayConfigSecurity): void { + switch (credentials.credentialsType) { + case DeviceCredentialsType.ACCESS_TOKEN: + this.updateAccessTokenCredentials(credentials, security); + break; + case DeviceCredentialsType.MQTT_BASIC: + this.updateMqttBasicCredentials(credentials); + break; + case DeviceCredentialsType.X509_CERTIFICATE: + break; + } + } + + private updateAccessTokenCredentials(credentials: DeviceCredentials, security: GatewayConfigSecurity): void { + this.basicFormGroup.get('thingsboard.security.accessToken').setValue(credentials.credentialsId, { emitEvent: false }); + if (security.type === SecurityTypes.TLS_ACCESS_TOKEN) { + this.basicFormGroup.get('thingsboard.security.caCert').setValue(security.caCert, { emitEvent: false }); + } + } + + private updateMqttBasicCredentials(credentials: DeviceCredentials): void { + const parsedValue = JSON.parse(credentials.credentialsValue); + this.basicFormGroup.get('thingsboard.security.clientId').setValue(parsedValue.clientId, { emitEvent: false }); + this.basicFormGroup.get('thingsboard.security.username').setValue(parsedValue.userName, { emitEvent: false }); + this.basicFormGroup.get('thingsboard.security.password').setValue(parsedValue.password, { emitEvent: false }); + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/gateway-configuration.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/gateway-configuration.component.ts index 317b616110..056628dd6a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/gateway-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/gateway-configuration.component.ts @@ -69,8 +69,8 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy { constructor(private fb: FormBuilder, private attributeService: AttributeService, private deviceService: DeviceService, - private cd: ChangeDetectorRef, - private dialog: MatDialog) { + private cd: ChangeDetectorRef + ) { this.gatewayConfigGroup = this.fb.group({ basicConfig: [], @@ -361,7 +361,7 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy { } private updateFormControls(thingsboard: GatewayGeneralConfig): void { - const { type, accessToken, ...securityConfig } = thingsboard.security || {}; + const { type, accessToken, ...securityConfig } = thingsboard.security ?? {}; this.initialCredentials = { deviceId: this.device as DeviceId, From 217247eddc9df40e80bbf99e784c4c6bf5213c8e Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 9 Sep 2024 10:37:37 +0300 Subject: [PATCH 34/80] UI: update rulenode config --- .../static/rulenode/rulenode-core-config.js | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js index 2c723830bd..0892bcd150 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -1,25 +1,25 @@ -System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/input","@angular/material/form-field","@angular/material/slide-toggle","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/button","@angular/material/icon","@angular/material/select","@angular/material/core","@angular/material/tooltip","@angular/material/expansion","rxjs","@shared/components/hint-tooltip-icon.component","@shared/components/help-popup.component","@shared/pipe/safe.pipe","@core/public-api","@shared/components/js-func.component","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/checkbox","@angular/material/chips","@shared/components/entity/entity-type-select.component","@shared/components/relation/relation-type-autocomplete.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","@shared/components/entity/entity-subtype-list.component","@home/components/relation/relation-filters.component","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,g,f,y,b,x,h,v,C,F,k,T,L,I,N,S,q,A,M,E,G,w,D,V,P,R,O,_,B,K,z,H,U,j,$,J,Q,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,ge,fe,ye,be,xe,he,ve,Ce,Fe,ke,Te,Le,Ie,Ne,Se,qe,Ae,Me,Ee,Ge,we,De,Ve,Pe,Re,Oe,_e,Be,Ke,ze,He,Ue,je,$e,Je,Qe,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt;return{setters:[function(e){t=e,n=e.Component,r=e.InjectionToken,o=e.Injectable,a=e.Inject,i=e.Optional,l=e.EventEmitter,s=e.Directive,m=e.Input,p=e.Output,d=e.NgModule,u=e.ViewChild,c=e.forwardRef},function(e){g=e.RuleNodeConfigurationComponent,f=e.AttributeScope,y=e.telemetryTypeTranslations,b=e.ScriptLanguage,x=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.EntityType,F=e.entityFields,k=e.PageComponent,T=e.messageTypeNames,L=e.MessageType,I=e.coerceBoolean,N=e.entitySearchDirectionTranslations,S=e,q=e.AlarmStatus,A=e.alarmStatusTranslations,M=e.SharedModule,E=e.AggregationType,G=e.aggregationTranslations,w=e.NotificationType,D=e.SlackChanelType,V=e.SlackChanelTypesTranslateMap},function(e){P=e},function(e){R=e,O=e.Validators,_=e.NgControl,B=e.NG_VALUE_ACCESSOR,K=e.NG_VALIDATORS,z=e.FormArray,H=e.FormGroup},function(e){U=e,j=e.DOCUMENT,$=e.CommonModule},function(e){J=e},function(e){Q=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e},function(e){oe=e},function(e){ae=e.Subject,ie=e.takeUntil,le=e.of,se=e.EMPTY,me=e.fromEvent},function(e){pe=e},function(e){de=e},function(e){ue=e},function(e){ce=e.getCurrentAuthState,ge=e,fe=e.isDefinedAndNotNull,ye=e.isEqual,be=e.deepTrim,xe=e.isObject,he=e.isNotEmptyStr},function(e){ve=e},function(e){Ce=e},function(e){Fe=e.ENTER,ke=e.COMMA,Te=e.SEMICOLON},function(e){Le=e},function(e){Ie=e},function(e){Ne=e},function(e){Se=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e},function(e){Ee=e.coerceBooleanProperty,Ge=e.coerceElement,we=e.coerceNumberProperty},function(e){De=e},function(e){Ve=e},function(e){Pe=e},function(e){Re=e},function(e){Oe=e.tap,_e=e.map,Be=e.startWith,Ke=e.mergeMap,ze=e.share,He=e.takeUntil,Ue=e.auditTime},function(e){je=e},function(e){$e=e},function(e){Je=e.HomeComponentsModule},function(e){Qe=e.__decorate},function(e){Ye=e},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e.normalizePassiveListenerOptions,pt=e}],execute:function(){class dt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",dt),dt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dt,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dt,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ut extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[O.required,O.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
\n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});const ct=new r("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class gt{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new ae,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}gt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,deps:[{token:t.NgZone},{token:j},{token:ct,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),gt.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:gt,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:a,args:[j]}]},{type:void 0,decorators:[{type:i},{type:a,args:[ct]}]}]}});class ft{constructor(e,t,n,r){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=r,this.cbOnSuccess=new l,this.cbOnError=new l,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:gt}],target:t.ɵɵFactoryTarget.Directive}),ft.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:ft,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,decorators:[{type:s,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:gt}]},propDecorators:{targetElm:[{type:m,args:["ngxClipboard"]}],container:[{type:m}],cbContent:[{type:m}],cbSuccessMsg:[{type:m}],cbOnSuccess:[{type:p}],cbOnError:[{type:p}]}});class yt{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,deps:[{token:gt},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),yt.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:yt,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,decorators:[{type:s,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:gt},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class bt{}bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,deps:[],target:t.ɵɵFactoryTarget.NgModule}),bt.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,declarations:[ft,yt],imports:[$],exports:[ft,yt]}),bt.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,imports:[[$]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,decorators:[{type:d,args:[{imports:[$],declarations:[ft,yt],exports:[ft,yt]}]}]});class xt{constructor(){this.textAlign="left"}}e("ExampleHintComponent",xt),xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,deps:[],target:t.ɵɵFactoryTarget.Component}),xt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xt,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xt,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:m}],popupHelpLink:[{type:m}],textAlign:[{type:m}]}});class ht extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===f.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vt extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.clearAlarmConfigForm}onConfigurationSet(e){this.clearAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[O.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===b.JS?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===b.TBEL?[O.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",vt),vt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),vt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vt,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ct extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.alarmSeverities=Object.keys(x),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[Fe,ke,Te],this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.createAlarmConfigForm}onConfigurationSet(e){this.createAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([O.required]),this.createAlarmConfigForm.get("severity").setValidators([O.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==b.TBEL||this.tbelEnabled||(r=b.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===b.JS?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===b.TBEL?[O.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",Ct),Ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ct,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ft extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.search-direction-from"],[v.TO,"tb.rulenode.search-direction-to"]]),this.entityType=C,this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[O.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[O.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]]})}validatorTriggers(){return["entityType","createEntityIfNotExists"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;if(t?this.createRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==C.DEVICE&&t!==C.ASSET)this.createRelationConfigForm.get("entityTypePattern").setValidators([]);else{const e=[O.pattern(/.*\S.*/)];this.createRelationConfigForm.get("createEntityIfNotExists").value&&e.push(O.required),this.createRelationConfigForm.get("entityTypePattern").setValidators(e)}this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",Ft),Ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ft,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n\n
\n
tb.rulenode.target-entity
\n
\n \n \n\n \n {{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n\n \n tb.rulenode.profile-name\n \n \n
\n\n \n\n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n\n
\n
tb.rulenode.target-entity
\n
\n \n \n\n \n {{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n\n \n tb.rulenode.profile-name\n \n \n
\n\n \n\n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.del-relation-direction-from"],[v.TO,"tb.rulenode.del-relation-direction-to"]]),this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.entityType=C,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[O.required]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([O.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n&&n!==C.TENANT?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",kt),kt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n \n
\n
\n
\n \n \n \n {{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n
\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n \n
\n
\n
\n \n \n \n {{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n
\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.deviceProfile}onConfigurationSet(e){this.deviceProfile=this.fb.group({persistAlarmRulesState:[!!e&&e.persistAlarmRulesState],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart]})}validatorTriggers(){return["persistAlarmRulesState"]}updateValidators(e){this.deviceProfile.get("persistAlarmRulesState").value?this.deviceProfile.get("fetchAlarmRulesStateOnStart").enable({emitEvent:!1}):(this.deviceProfile.get("fetchAlarmRulesStateOnStart").setValue(!1,{emitEvent:!1}),this.deviceProfile.get("fetchAlarmRulesStateOnStart").disable({emitEvent:!1})),this.deviceProfile.get("fetchAlarmRulesStateOnStart").updateValueAndValidity({emitEvent:e})}}e("DeviceProfileConfigComponent",Tt),Tt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.device-profile-node-hint
\n
\n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
\n
\n',dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
\n
tb.rulenode.device-profile-node-hint
\n
\n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Lt extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[O.required,O.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[O.required,O.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}var It;e("GeneratorConfigComponent",Lt),Lt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Lt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lt,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n \n \n \n
\n\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:qe.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n \n \n \n
\n\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(It||(It={}));const Nt=new Map([[It.CUSTOMER,"tb.rulenode.originator-customer"],[It.TENANT,"tb.rulenode.originator-tenant"],[It.RELATED,"tb.rulenode.originator-related"],[It.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[It.ENTITY,"tb.rulenode.originator-entity"]]),St=new Map([[It.CUSTOMER,"tb.rulenode.originator-customer-desc"],[It.TENANT,"tb.rulenode.originator-tenant-desc"],[It.RELATED,"tb.rulenode.originator-related-entity-desc"],[It.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[It.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),qt=[F.createdTime,F.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},F.firstName,F.lastName,F.email,F.title,F.country,F.state,F.city,F.address,F.address2,F.zip,F.phone,F.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],At=new Map([["type","profileName"],["createdTime","createdTime"],["name","name"],["firstName","firstName"],["lastName","lastName"],["email","email"],["title","title"],["country","country"],["state","state"],["city","city"],["address","address"],["address2","address2"],["zip","zip"],["phone","phone"],["label","label"],["id","id"],["additionalInfo","additionalInfo"]]);var Mt;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Mt||(Mt={}));const Et=new Map([[Mt.CIRCLE,"tb.rulenode.perimeter-circle"],[Mt.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Gt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Gt||(Gt={}));const wt=new Map([[Gt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Gt.SECONDS,"tb.rulenode.time-unit-seconds"],[Gt.MINUTES,"tb.rulenode.time-unit-minutes"],[Gt.HOURS,"tb.rulenode.time-unit-hours"],[Gt.DAYS,"tb.rulenode.time-unit-days"]]);var Dt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(Dt||(Dt={}));const Vt=new Map([[Dt.METER,"tb.rulenode.range-unit-meter"],[Dt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[Dt.FOOT,"tb.rulenode.range-unit-foot"],[Dt.MILE,"tb.rulenode.range-unit-mile"],[Dt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Pt;!function(e){e.ID="ID",e.TITLE="TITLE",e.COUNTRY="COUNTRY",e.STATE="STATE",e.CITY="CITY",e.ZIP="ZIP",e.ADDRESS="ADDRESS",e.ADDRESS2="ADDRESS2",e.PHONE="PHONE",e.EMAIL="EMAIL",e.ADDITIONAL_INFO="ADDITIONAL_INFO"}(Pt||(Pt={}));const Rt=new Map([[Pt.ID,"tb.rulenode.entity-details-id"],[Pt.TITLE,"tb.rulenode.entity-details-title"],[Pt.COUNTRY,"tb.rulenode.entity-details-country"],[Pt.STATE,"tb.rulenode.entity-details-state"],[Pt.CITY,"tb.rulenode.entity-details-city"],[Pt.ZIP,"tb.rulenode.entity-details-zip"],[Pt.ADDRESS,"tb.rulenode.entity-details-address"],[Pt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Pt.PHONE,"tb.rulenode.entity-details-phone"],[Pt.EMAIL,"tb.rulenode.entity-details-email"],[Pt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var Ot;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(Ot||(Ot={}));const _t=new Map([[Ot.FIRST,"tb.rulenode.first"],[Ot.LAST,"tb.rulenode.last"],[Ot.ALL,"tb.rulenode.all"]]),Bt=new Map([[Ot.FIRST,"tb.rulenode.first-mode-hint"],[Ot.LAST,"tb.rulenode.last-mode-hint"],[Ot.ALL,"tb.rulenode.all-mode-hint"]]);var Kt,zt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Kt||(Kt={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(zt||(zt={}));const Ht=new Map([[zt.ATTRIBUTES,"tb.rulenode.attributes"],[zt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[zt.FIELDS,"tb.rulenode.fields"]]),Ut=new Map([[zt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[zt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[zt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),jt=new Map([[Kt.ASC,"tb.rulenode.ascending"],[Kt.DESC,"tb.rulenode.descending"]]);var $t;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}($t||($t={}));const Jt=new Map([[$t.STANDARD,"tb.rulenode.sqs-queue-standard"],[$t.FIFO,"tb.rulenode.sqs-queue-fifo"]]),Qt=["anonymous","basic","cert.PEM"],Yt=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Wt=["sas","cert.PEM"],Zt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var Xt;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}(Xt||(Xt={}));const en=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],tn=new Map([["US-ASCII","tb.rulenode.charset-us-ascii"],["ISO-8859-1","tb.rulenode.charset-iso-8859-1"],["UTF-8","tb.rulenode.charset-utf-8"],["UTF-16BE","tb.rulenode.charset-utf-16be"],["UTF-16LE","tb.rulenode.charset-utf-16le"],["UTF-16","tb.rulenode.charset-utf-16"]]);var nn;!function(e){e.CUSTOM="CUSTOM",e.ADD="ADD",e.SUB="SUB",e.MULT="MULT",e.DIV="DIV",e.SIN="SIN",e.SINH="SINH",e.COS="COS",e.COSH="COSH",e.TAN="TAN",e.TANH="TANH",e.ACOS="ACOS",e.ASIN="ASIN",e.ATAN="ATAN",e.ATAN2="ATAN2",e.EXP="EXP",e.EXPM1="EXPM1",e.SQRT="SQRT",e.CBRT="CBRT",e.GET_EXP="GET_EXP",e.HYPOT="HYPOT",e.LOG="LOG",e.LOG10="LOG10",e.LOG1P="LOG1P",e.CEIL="CEIL",e.FLOOR="FLOOR",e.FLOOR_DIV="FLOOR_DIV",e.FLOOR_MOD="FLOOR_MOD",e.ABS="ABS",e.MIN="MIN",e.MAX="MAX",e.POW="POW",e.SIGNUM="SIGNUM",e.RAD="RAD",e.DEG="DEG"}(nn||(nn={}));const rn=new Map([[nn.CUSTOM,{value:nn.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[nn.ADD,{value:nn.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[nn.SUB,{value:nn.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[nn.MULT,{value:nn.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[nn.DIV,{value:nn.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[nn.SIN,{value:nn.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[nn.SINH,{value:nn.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[nn.COS,{value:nn.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[nn.COSH,{value:nn.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[nn.TAN,{value:nn.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[nn.TANH,{value:nn.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[nn.ACOS,{value:nn.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[nn.ASIN,{value:nn.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[nn.ATAN,{value:nn.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[nn.ATAN2,{value:nn.ATAN2,name:"2-argument arc tangent",description:"Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta)",minArgs:2,maxArgs:2}],[nn.EXP,{value:nn.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[nn.EXPM1,{value:nn.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[nn.SQRT,{value:nn.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[nn.CBRT,{value:nn.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[nn.GET_EXP,{value:nn.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[nn.HYPOT,{value:nn.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[nn.LOG,{value:nn.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[nn.LOG10,{value:nn.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[nn.LOG1P,{value:nn.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[nn.CEIL,{value:nn.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[nn.FLOOR,{value:nn.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[nn.FLOOR_DIV,{value:nn.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[nn.FLOOR_MOD,{value:nn.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[nn.ABS,{value:nn.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[nn.MIN,{value:nn.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[nn.MAX,{value:nn.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[nn.POW,{value:nn.POW,name:"Raise to a power",description:"Returns the value of the first argument raised to the power of the second argument",minArgs:2,maxArgs:2}],[nn.SIGNUM,{value:nn.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[nn.RAD,{value:nn.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[nn.DEG,{value:nn.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var on,an,ln;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(on||(on={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(an||(an={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(ln||(ln={}));const sn=new Map([[ln.DATA,"tb.rulenode.message-to-metadata"],[ln.METADATA,"tb.rulenode.metadata-to-message"]]),mn=(new Map([[ln.DATA,"tb.rulenode.from-message"],[ln.METADATA,"tb.rulenode.from-metadata"]]),new Map([[ln.DATA,"tb.rulenode.message"],[ln.METADATA,"tb.rulenode.metadata"]])),pn=new Map([[ln.DATA,"tb.rulenode.message"],[ln.METADATA,"tb.rulenode.message-metadata"]]),dn=new Map([[on.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[on.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[on.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[on.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[on.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),un=new Map([[an.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[an.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[an.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[an.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),cn=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var gn,fn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(gn||(gn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(fn||(fn={}));const yn=new Map([[gn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[gn.SERVER_SCOPE,"tb.rulenode.server-scope"],[gn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var bn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(bn||(bn={}));const xn=new Map([[bn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[bn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class hn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Mt,this.perimeterTypes=Object.keys(Mt),this.perimeterTypeTranslationMap=Et,this.rangeUnits=Object.keys(Dt),this.rangeUnitTranslationMap=Vt,this.presenceMonitoringStrategies=xn,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Gt),this.timeUnitsTranslationMap=wt,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[O.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[O.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[O.required]],perimeterType:[e?e.perimeterType:null,[O.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[O.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[O.required,O.min(1),O.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[O.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Mt.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoActionConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Mt.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",hn),hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n
\n
\n
{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
\n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
\n
{{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
\n
\n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n
\n
\n
{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
\n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
\n
{{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
\n
\n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vn extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-to-string-function"}configForm(){return this.logConfigForm}onConfigurationSet(e){this.logConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Cn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[O.required,O.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[O.required]]})}}e("MsgCountConfigComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Fn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([O.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([O.required,O.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class kn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToCloudConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]]})}}e("PushToEdgeConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ln extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]],sessionIdMetaDataAttribute:[e?e.sessionIdMetaDataAttribute:null,[]],requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.session-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.session-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class In extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[O.required,O.min(0)]]})}}e("RpcRequestConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[O.required]],value:[e[n],[O.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[O.required]],value:["",[O.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:B,useExisting:c((()=>Nn)),multi:!0},{provide:K,useExisting:c((()=>Nn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:De.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ve.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:B,useExisting:c((()=>Nn)),multi:!0},{provide:K,useExisting:c((()=>Nn)),multi:!0}],template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],required:[{type:m}]}});class Sn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[O.required,O.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[O.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class qn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[O.required,O.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.default-ttl\n \n \n help\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
\n \n tb.rulenode.default-ttl\n \n \n help\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class An extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[]],createCustomerIfNotExists:[!!e&&e?.createCustomerIfNotExists,[]]})}validatorTriggers(){return["createCustomerIfNotExists"]}updateValidators(e){this.unassignCustomerConfigForm.get("createCustomerIfNotExists").value?this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)]):this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([]),this.unassignCustomerConfigForm.get("customerNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("UnassignCustomerConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n
\n\n
\n
\n \n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n \n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
\n
\n\n
\n
\n \n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n \n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Mn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendRestApiCallReplyConfigForm}onConfigurationSet(e){this.sendRestApiCallReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]],serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]]})}}e("SendRestApiCallReplyConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-action-node-send-rest-api-call-reply-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n',dependencies:[{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-action-node-send-rest-api-call-reply-config",template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class En extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[Fe,ke,Te]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[O.required]],keys:[e?e.keys:null,[O.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:u,args:["attributeChipList"]}]}});class Gn extends k{get function(){return this.functionValue}set function(e){e&&this.functionValue!==e&&(this.functionValue=e,this.setupArgumentsFormGroup(!0))}constructor(e,t){super(e),this.store=e,this.fb=t,this.maxArgs=16,this.minArgs=1,this.displayArgumentName=!1,this.mathFunctionMap=rn,this.ArgumentType=on,this.attributeScopeMap=yn,this.argumentTypeMap=dn,this.arguments=Object.values(on),this.attributeScope=Object.values(gn),this.propagateChange=null,this.valueChangeSubscription=[]}ngOnInit(){this.argumentsFormGroup=this.fb.group({arguments:this.fb.array([])}),this.valueChangeSubscription.push(this.argumentsFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))),this.setupArgumentsFormGroup()}onDrop(e){const t=this.argumentsFormArray,n=t.at(e.previousIndex);t.removeAt(e.previousIndex),t.insert(e.currentIndex,n),this.updateArgumentNames()}get argumentsFormArray(){return this.argumentsFormGroup.get("arguments")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.argumentsFormGroup.disable({emitEvent:!1}):(this.argumentsFormGroup.enable({emitEvent:!1}),this.argumentsFormArray.controls.forEach((e=>this.updateArgumentControlValidators(e))))}ngOnDestroy(){this.valueChangeSubscription.length&&this.valueChangeSubscription.forEach((e=>e.unsubscribe()))}writeValue(e){const t=[];e&&e.forEach(((e,n)=>{t.push(this.createArgumentControl(e,n))})),this.argumentsFormGroup.setControl("arguments",this.fb.array(t),{emitEvent:!1}),this.setupArgumentsFormGroup()}removeArgument(e){this.argumentsFormArray.removeAt(e),this.updateArgumentNames()}addArgument(e=!0){const t=this.argumentsFormArray,n=this.createArgumentControl(null,t.length);t.push(n,{emitEvent:e})}validate(e){return this.argumentsFormGroup.valid?null:{argumentsRequired:!0}}setupArgumentsFormGroup(e=!1){if(this.function&&(this.maxArgs=this.mathFunctionMap.get(this.function).maxArgs,this.minArgs=this.mathFunctionMap.get(this.function).minArgs,this.displayArgumentName=this.function===nn.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([O.minLength(this.minArgs),O.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===on.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==on.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(cn[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:B,useExisting:c((()=>Gn)),multi:!0},{provide:K,useExisting:c((()=>Gn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:U.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Pe.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:Pe.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Re.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Re.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Re.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Ve.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:B,useExisting:c((()=>Gn)),multi:!0},{provide:K,useExisting:c((()=>Gn)),multi:!0}],template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],function:[{type:m}]}});class wn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.searchText="",this.dirty=!1,this.mathOperation=[...rn.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(Oe((e=>{let t;t="string"==typeof e&&nn[e]?nn[e]:null,this.updateView(t)})),_e((e=>(this.searchText=e||"",e?this._filter(e):this.mathOperation.slice()))))}_filter(e){const t=e.toLowerCase();return this.mathOperation.filter((e=>e.name.toLowerCase().includes(t)||e.value.toLowerCase().includes(t)))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.mathFunctionForm.disable({emitEvent:!1}):this.mathFunctionForm.enable({emitEvent:!1})}mathFunctionDisplayFn(e){if(e){const t=rn.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",wn),wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:B,useExisting:c((()=>wn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:je.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:je.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:$e.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:B,useExisting:c((()=>wn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.UntypedFormBuilder}]},propDecorators:{required:[{type:m}],disabled:[{type:m}],operationInput:[{type:u,args:["operationInput",{static:!0}]}]}});class Dn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=nn,this.ArgumentTypeResult=an,this.argumentTypeResultMap=un,this.attributeScopeMap=yn,this.argumentsResult=Object.values(an),this.attributeScopeResult=Object.values(fn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[O.required]],arguments:[e?e.arguments:null,[O.required]],customFunction:[e?e.customFunction:"",[O.required]],result:this.fb.group({type:[e?e.result.type:null,[O.required]],attributeScope:[e?e.result.attributeScope:null,[O.required]],key:[e?e.result.key:"",[O.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===nn.CUSTOM?(this.mathFunctionConfigForm.get("customFunction").enable({emitEvent:!1}),null===this.mathFunctionConfigForm.get("customFunction").value&&this.mathFunctionConfigForm.get("customFunction").patchValue("(x - 32) / 1.8",{emitEvent:!1})):this.mathFunctionConfigForm.get("customFunction").disable({emitEvent:!1}),n===an.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Gn,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:wn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Vn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=T,this.eventOptions=[L.CONNECT_EVENT,L.ACTIVITY_EVENT,L.DISCONNECT_EVENT,L.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:fe(e?.event)?e.event:L.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[O.required]]})}}e("DeviceStateConfigComponent",Vn),Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vn,selector:"tb-action-node-device-state-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,decorators:[{type:n,args:[{selector:"tb-action-node-device-state-config",template:'
\n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Pn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new ae,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof H){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ye(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(ie(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Pn),Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,deps:[{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:c((()=>Pn)),multi:!0},{provide:K,useExisting:c((()=>Pn)),multi:!0}],ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Pn.prototype,"disabled",void 0),Qe([I()],Pn.prototype,"uniqueKeyValuePairValidator",void 0),Qe([I()],Pn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:B,useExisting:c((()=>Pn)),multi:!0},{provide:K,useExisting:c((()=>Pn)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class Rn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.entityType=C,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],relationType:[null],deviceTypes:[null,[O.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",Rn),Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rn,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Rn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ye.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:B,useExisting:c((()=>Rn)),multi:!0}],template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class On extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[O.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",On),On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),On.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:On,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>On)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:We.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:B,useExisting:c((()=>On)),multi:!0}],template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class _n extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.truncate=n,this.fb=r,this.placeholder="tb.rulenode.add-message-type",this.separatorKeysCodes=[Fe,ke,Te],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(L))this.messageTypesList.push({name:T.get(L[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Be(""),_e((e=>e||"")),Ke((e=>this.fetchMessageTypes(e))),ze())}setDisabledState(e){this.disabled=e,this.disabled?this.messageTypeConfigForm.disable({emitEvent:!1}):this.messageTypeConfigForm.enable({emitEvent:!1})}writeValue(e){this.searchText="",this.messageTypes.length=0,e&&e.forEach((e=>{const t=this.messageTypesList.find((t=>t.value===e));t?this.messageTypes.push({name:t.name,value:t.value}):this.messageTypes.push({name:e,value:e})}))}displayMessageTypeFn(e){return e?e.name:void 0}textIsNotEmpty(e){return e&&e.length>0}createMessageType(e,t){e.preventDefault(),this.transformMessageType(t)}add(e){this.transformMessageType(e.value)}fetchMessageTypes(e){if(this.searchText=e,this.searchText&&this.searchText.length){const e=this.searchText.toUpperCase();return le(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return le(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:P.Store},{token:Z.TranslateService},{token:S.TruncatePipe},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:B,useExisting:c((()=>_n)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:je.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:je.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:je.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:Ie.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Ie.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Ie.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Ie.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:$e.HighlightPipe,name:"highlight"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:B,useExisting:c((()=>_n)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:S.TruncatePipe},{type:R.FormBuilder}]},propDecorators:{required:[{type:m}],label:[{type:m}],placeholder:[{type:m}],disabled:[{type:m}],chipList:[{type:u,args:["chipList",{static:!1}]}],matAutocomplete:[{type:u,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:u,args:["messageTypeInput",{static:!1}]}]}});class Bn extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=Qt,this.credentialsTypeTranslationsMap=Yt,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[O.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){fe(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([O.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[O.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(O.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:B,useExisting:c((()=>Bn)),multi:!0},{provide:K,useExisting:c((()=>Bn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:U.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:oe.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:oe.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:B,useExisting:c((()=>Bn)),multi:!0},{provide:K,useExisting:c((()=>Bn)),multi:!0}],template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{required:[{type:m}],disableCertPemCredentials:[{type:m}],passwordFieldRequired:[{type:m}]}});class Kn{set required(e){this.requiredValue!==e&&(this.requiredValue=e,this.updateValidators())}get required(){return this.requiredValue}constructor(e){this.fb=e,this.subscriptSizing="fixed",this.messageTypes=[{name:"Post attributes",value:"POST_ATTRIBUTES_REQUEST"},{name:"Post telemetry",value:"POST_TELEMETRY_REQUEST"},{name:"Custom",value:""}],this.propagateChange=()=>{},this.destroy$=new ae,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[O.required]],messageType:[{value:null,disabled:!0},[O.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(ie(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(ie(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[O.required,O.maxLength(255)]:[O.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Kn)),multi:!0},{provide:K,useExisting:c((()=>Kn)),multi:!0}],ngImport:t,template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:ft,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Kn.prototype,"disabled",void 0),Qe([I()],Kn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:B,useExisting:c((()=>Kn)),multi:!0},{provide:K,useExisting:c((()=>Kn)),multi:!0}],template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder}]},propDecorators:{subscriptSizing:[{type:m}],disabled:[{type:m}],required:[{type:m}]}});class zn{constructor(e,t){this.fb=e,this.translate=t,this.translation=mn,this.propagateChange=()=>{},this.destroy$=new ae,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(He(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:B,useExisting:c((()=>zn)),multi:!0}],ngImport:t,template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Ie.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Ie.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:B,useExisting:c((()=>zn)),multi:!0}],template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n'}]}],ctorParameters:function(){return[{type:R.FormBuilder},{type:Z.TranslateService}]},propDecorators:{labelText:[{type:m}],translation:[{type:m}]}});class Hn extends k{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new ae,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof H){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return ye(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(_),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(He(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[O.required]],value:[t.value,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)fe(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[O.required]],value:["",[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(He(this.destroy$)).subscribe((t=>{const n=At.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:P.Store},{token:Z.TranslateService},{token:t.Injector},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:B,useExisting:c((()=>Hn)),multi:!0},{provide:K,useExisting:c((()=>Hn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Ve.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:U.AsyncPipe,name:"async"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),Qe([I()],Hn.prototype,"disabled",void 0),Qe([I()],Hn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:B,useExisting:c((()=>Hn)),multi:!0},{provide:K,useExisting:c((()=>Hn)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:t.Injector},{type:R.FormBuilder}]},propDecorators:{selectOptions:[{type:m}],disabled:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],targetKeyPrefix:[{type:m}],selectText:[{type:m}],selectRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class Un extends k{get required(){return this.requiredValue}set required(e){this.requiredValue=Ee(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[O.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:B,useExisting:c((()=>Un)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:We.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:B,useExisting:c((()=>Un)),multi:!0}],template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class jn{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new ae,this.separatorKeysCodes=[Fe,ke,Te],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(O.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(He(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||fe(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:B,useExisting:c((()=>jn)),multi:!0},{provide:K,useExisting:jn,multi:!0}],ngImport:t,template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:B,useExisting:c((()=>jn)),multi:!0},{provide:K,useExisting:jn,multi:!0}],template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:Z.TranslateService},{type:R.FormBuilder}]},propDecorators:{popupHelpLink:[{type:m}]}});class $n extends k{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new ae,this.alarmStatus=q,this.alarmStatusTranslations=A}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(He(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:c((()=>$n)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:Ie.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Ie.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:B,useExisting:c((()=>$n)),multi:!0}],template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Jn{}e("RulenodeCoreConfigCommonModule",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Jn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Jn,declarations:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt],imports:[$,M,Je],exports:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt]}),Jn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,imports:[$,M,Je]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:d,args:[{declarations:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt],imports:[$,M,Je],exports:[Pn,Rn,On,_n,Bn,Gn,wn,Kn,Nn,zn,Hn,Un,jn,$n,xt]}]}]});class Qn{}e("RuleNodeCoreConfigActionModule",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Qn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Qn,declarations:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn],imports:[$,M,Je,Jn],exports:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn]}),Qn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,imports:[$,M,Je,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:d,args:[{declarations:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn],imports:[$,M,Je,Jn],exports:[En,ht,qn,In,vn,ut,vt,Ct,Ft,Fn,kt,Lt,hn,Cn,Ln,Sn,An,Mn,Tt,Tn,kn,Dn,Vn]}]}]});class Yn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[Fe,ke,Te]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[O.min(0),O.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]],excludeZeroDeltas:[e.excludeZeroDeltas,[]]})}prepareInputConfig(e){return{inputValueKey:fe(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:fe(e?.outputValueKey)?e.outputValueKey:null,useCache:!fe(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!fe(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:fe(e?.periodValueKey)?e.periodValueKey:null,round:fe(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!fe(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative,excludeZeroDeltas:!!fe(e?.excludeZeroDeltas)&&e.excludeZeroDeltas}}prepareOutputConfig(e){return be(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([O.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Yn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Yn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n \n
\n
\n
\n",dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n \n
\n
\n
\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Wn extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ht.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.customerAttributesConfigForm}prepareOutputConfig(e){const t={};for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,be(e)}prepareInputConfig(e){let t,n;return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Zn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[O.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return xe(e)&&(e.attributesControl={clientAttributeNames:fe(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:fe(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:fe(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!fe(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:fe(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!fe(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Rn,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:jn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class Xn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Pt))this.predefinedValues.push({value:Pt[e],name:this.translate.instant(Rt.get(Pt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=fe(e?.addToMetadata)?e.addToMetadata?ln.METADATA:ln.DATA:e?.fetchTo?e.fetchTo:ln.DATA,{detailsList:fe(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class er extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[Fe,ke,Te],this.aggregationTypes=E,this.aggregations=Object.values(E),this.aggregationTypesTranslations=G,this.fetchMode=Ot,this.samplingOrders=Object.values(Kt),this.samplingOrdersTranslate=jt,this.timeUnits=Object.values(Gt),this.timeUnitsTranslationMap=wt,this.deduplicationStrategiesHintTranslations=Bt,this.headerOptions=[],this.timeUnitMap={[Gt.MILLISECONDS]:1,[Gt.SECONDS]:1e3,[Gt.MINUTES]:6e4,[Gt.HOURS]:36e5,[Gt.DAYS]:864e5},this.intervalValidator=()=>e=>e.get("startInterval").value*this.timeUnitMap[e.get("startIntervalTimeUnit").value]<=e.get("endInterval").value*this.timeUnitMap[e.get("endIntervalTimeUnit").value]?{intervalError:!0}:null;for(const e of _t.keys())this.headerOptions.push({value:e,name:this.translate.instant(_t.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[O.required]],aggregation:[e.aggregation,[O.required]],fetchMode:[e.fetchMode,[O.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,be(e)}prepareInputConfig(e){return xe(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:fe(e?.aggregation)?e.aggregation:E.NONE,fetchMode:fe(e?.fetchMode)?e.fetchMode:Ot.FIRST,orderBy:fe(e?.orderBy)?e.orderBy:Kt.ASC,limit:fe(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!fe(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:fe(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:fe(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Gt.MINUTES,endInterval:fe(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:fe(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Gt.MINUTES},startIntervalPattern:fe(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:fe(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===Ot.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([O.required,O.min(2),O.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([O.required,O.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([O.required,O.min(1),O.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([O.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===Ot.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===E.NONE}}e("GetTelemetryFromDatabaseConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class tr extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.originatorAttributesConfigForm}onConfigurationSet(e){this.originatorAttributesConfigForm=this.fb.group({tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return xe(e)&&(e.attributesControl={clientAttributeNames:fe(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:fe(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:fe(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:fe(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!fe(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA,tellFailureIfAbsent:!!fe(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:fe(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:P.Store},{token:Z.TranslateService},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:jn,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:Z.TranslateService},{type:R.FormBuilder}]}});class nr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of qt)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return be(e)}prepareInputConfig(e){return{dataMapping:fe(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:fe(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[O.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n',dependencies:[{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=zt,this.msgMetadataLabelTranslations=Ut,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(qt))this.originatorFields.push({value:qt[e].value,name:this.translate.instant(qt[e].name)});for(const e of Ht.keys())this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===zt.FIELDS?(e.dataMapping=e.svMap,delete e.svMap):(e.dataMapping=e.kvMap,delete e.kvMap);const t={};if(e&&e.dataMapping)for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,delete e.svMap,delete e.kvMap,be(e)}prepareInputConfig(e){let t,n,r={[F.name.value]:`relatedEntity${this.translate.instant(F.name.name)}`},o={serialNumber:"sn"};return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,t===zt.FIELDS?r=n:o=n,{relationsQuery:fe(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[O.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[O.required]],svMap:[e.svMap,[O.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===zt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:On,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Hn,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ht.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ht.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=fe(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:fe(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=fe(e?.attrMapping)?e.attrMapping:fe(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[O.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:W.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class ar extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:fe(e?.fetchTo)?e.fetchTo:ln.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class ir{}e("RulenodeCoreConfigEnrichmentModule",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[],target:t.ɵɵFactoryTarget.NgModule}),ir.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:ir,declarations:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar],imports:[$,M,Jn],exports:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar]}),ir.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:d,args:[{declarations:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar],imports:[$,M,Jn],exports:[Wn,Xn,Zn,tr,nr,er,rr,or,Yn,ar]}]}]});class lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Wt,this.azureIotHubCredentialsTypeTranslationsMap=Zt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[O.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[O.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([O.required]);break;case"cert.PEM":t.get("privateKey").setValidators([O.required]),t.get("privateKeyFileName").setValidators([O.required]),t.get("cert").setValidators([O.required]),t.get("certFileName").setValidators([O.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:lr,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:U.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:U.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:oe.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:R.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class sr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=en,this.ToByteStandartCharsetTypeTranslationMap=tn}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[O.required]],retries:[e?e.retries:null,[O.min(0)]],batchSize:[e?e.batchSize:null,[O.min(0)]],linger:[e?e.linger:null,[O.min(0)]],bufferMemory:[e?e.bufferMemory:null,[O.min(0)]],acks:[e?e.acks:null,[O.required]],keySerializer:[e?e.keySerializer:null,[O.required]],valueSerializer:[e?e.valueSerializer:null,[O.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([O.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class mr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[O.required]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[O.required,O.min(1),O.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&he(e.clientId))},[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){he(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Bn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=w,this.entityType=C}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[O.required]],targets:[e?e.targets:[],[O.required]]})}}e("NotificationConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n',dependencies:[{kind:"component",type:tt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:nt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class dr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[O.required]],topicName:[e?e.topicName:null,[O.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[O.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[O.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ze.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[O.required]],port:[e?e.port:null,[O.required,O.min(1),O.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[O.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[O.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys(Xt)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[O.required]],requestMethod:[e?e.requestMethod:null,[O.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[O.min(0)]],headers:[e?e.headers:null,[]],credentials:[e?e.credentials:null,[]]})}validatorTriggers(){return["useSimpleClientHttpFactory","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("enableProxy").value,r=this.restApiCallConfigForm.get("useSystemProxyProperties").value;n&&!r?(this.restApiCallConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([O.min(0)])),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Bn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n
\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class gr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([O.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([O.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([O.required,O.min(1),O.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([O.required,O.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[O.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[O.required,O.min(1),O.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:rt.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Xe.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[O.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[O.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([O.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ot.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class yr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(D),this.slackChanelTypesTranslateMap=V}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[O.required]],conversationType:[e?e.conversationType:null,[O.required]],conversation:[e?e.conversation:null,[O.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([O.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Le.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:at.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:at.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:it.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class br extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[O.required]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SnsConfigComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class xr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=$t,this.sqsQueueTypes=Object.keys($t),this.sqsQueueTypeTranslationsMap=Jt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[O.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[O.required]],delaySeconds:[e?e.delaySeconds:null,[O.min(0),O.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[O.required]],secretAccessKey:[e?e.secretAccessKey:null,[O.required]],region:[e?e.region:null,[O.required]]})}}e("SqsConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ue.SafePipe,name:"safe"},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.lambdaConfigForm}onConfigurationSet(e){this.lambdaConfigForm=this.fb.group({functionName:[e?e.functionName:null,[O.required]],qualifier:[e?e.qualifier:null,[]],accessKey:[e?e.accessKey:null,[O.required]],secretKey:[e?e.secretKey:null,[O.required]],region:[e?e.region:null,[O.required]],connectionTimeout:[e?e.connectionTimeout:null,[O.required,O.min(0)]],requestTimeout:[e?e.requestTimeout:null,[O.required,O.min(0)]],tellFailureIfFuncThrowsExc:[!!e&&e.tellFailureIfFuncThrowsExc,[]]})}}e("LambdaConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-external-node-lambda-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n
tb.rulenode.function-configuration
\n
\n \n \n
\n \n {{\'tb.rulenode.function-name\' | translate}}\n \n \n {{\'tb.rulenode.function-name-required\' | translate}}\n \n \n \n {{\'tb.rulenode.qualifier\' | translate}}\n \n tb.rulenode.qualifier-hint\n \n
\n
\n\n
\n \n \n tb.rulenode.aws-credentials\n \n
\n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n tb.rulenode.connection-timeout\n \n \n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n \n help\n \n \n tb.rulenode.request-timeout\n \n \n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n \n help\n \n
\n
\n \n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-external-node-lambda-config",template:'
\n
\n
\n
tb.rulenode.function-configuration
\n
\n \n \n
\n \n {{\'tb.rulenode.function-name\' | translate}}\n \n \n {{\'tb.rulenode.function-name-required\' | translate}}\n \n \n \n {{\'tb.rulenode.qualifier\' | translate}}\n \n tb.rulenode.qualifier-hint\n \n
\n
\n\n
\n \n \n tb.rulenode.aws-credentials\n \n
\n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n tb.rulenode.connection-timeout\n \n \n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n \n help\n \n \n tb.rulenode.request-timeout\n \n \n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n \n help\n \n
\n
\n \n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class vr{}e("RulenodeCoreConfigExternalModule",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),vr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:vr,declarations:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr],imports:[$,M,Je,Jn],exports:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr]}),vr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,imports:[$,M,Je,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:d,args:[{declarations:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr],imports:[$,M,Je,Jn],exports:[br,xr,hr,dr,sr,mr,pr,ur,cr,gr,lr,fr,yr]}]}]});class Cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:fe(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[O.required]]})}}e("CheckAlarmStatusComponent",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:$n,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:fe(e?.messageNames)?e.messageNames:[],metadataNames:fe(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!fe(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:fe(e?.messageNames)?e.messageNames:[],metadataNames:fe(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(O.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=N}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!fe(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:fe(e?.direction)?e.direction:null,entityType:fe(e?.entityType)?e.entityType:null,entityId:fe(e?.entityId)?e.entityId:null,relationType:fe(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[O.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[O.required]:[]],relationType:[e.relationType,[O.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[O.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"component",type:Se.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Tr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Mt,this.perimeterTypes=Object.values(Mt),this.perimeterTypeTranslationMap=Et,this.rangeUnits=Object.values(Dt),this.rangeUnitTranslationMap=Vt,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:fe(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:fe(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:fe(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!fe(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:fe(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:fe(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:fe(e?.centerLongitude)?e.centerLongitude:null,range:fe(e?.range)?e.range:null,rangeUnit:fe(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:fe(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[O.required]],longitudeKeyName:[e.longitudeKeyName,[O.required]],perimeterType:[e.perimeterType,[O.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([O.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Mt.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([O.required,O.min(-90),O.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([O.required,O.min(-180),O.max(180)]),this.geoFilterConfigForm.get("range").setValidators([O.required,O.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([O.required]),this.defaultPaddingEnable=!1),t||n!==Mt.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([O.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:W.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:R.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:fe(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[O.required]]})}}e("MessageTypeConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:_n,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ir extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.RULE_CHAIN,C.RULE_NODE,C.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:fe(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[O.required]]})}}e("OriginatorTypeConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:st.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:W.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Nr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:fe(e?.scriptLang)?e.scriptLang:b.JS,jsScript:fe(e?.jsScript)?e.jsScript:null,tbelScript:fe(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Sr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[O.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:fe(e?.scriptLang)?e.scriptLang:b.JS,jsScript:fe(e?.jsScript)?e.jsScript:null,tbelScript:fe(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:P.Store},{token:R.UntypedFormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class qr{}e("RuleNodeCoreConfigFilterModule",qr),qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),qr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:qr,declarations:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr],imports:[$,M,Jn],exports:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr]}),qr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,decorators:[{type:d,args:[{declarations:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr],imports:[$,M,Jn],exports:[Fr,kr,Tr,Lr,Ir,Nr,Sr,Cr]}]}]});class Ar extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=It,this.originatorSources=Object.keys(It),this.originatorSourceTranslationMap=Nt,this.originatorSourceDescTranslationMap=St,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.USER,C.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[O.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===It.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([O.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===It.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([O.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([O.required,O.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Ar),Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ar,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n',dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Pe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Pe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:On,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Mr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ce(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-transformer-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[O.required]],jsScript:[e?e.jsScript:null,[O.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[O.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[O.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Mr),Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,deps:[{token:P.Store},{token:R.FormBuilder},{token:ge.NodeScriptTestService},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mr,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ve.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:X.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:X.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Ce.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:ge.NodeScriptTestService},{type:Z.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - const Er=mt({passive:!0});class Gr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return se;const t=Ge(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new ae,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,Er),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,Er)}}),r}stopMonitoring(e){const t=Ge(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[{token:pt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Gr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:pt.Platform},{type:t.NgZone}]}});class wr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new l}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}wr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:wr,deps:[{token:t.ElementRef},{token:Gr}],target:t.ɵɵFactoryTarget.Directive}),wr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:wr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:wr,decorators:[{type:s,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Gr}]},propDecorators:{cdkAutofill:[{type:p}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Dr{get minRows(){return this._minRows}set minRows(e){this._minRows=we(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=we(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=Ee(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new ae,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();me(e,"resize").pipe(Ue(16),He(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,deps:[{token:t.ElementRef},{token:pt.Platform},{token:t.NgZone},{token:j,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Dr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Dr,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,decorators:[{type:s,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:pt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:i},{type:a,args:[j]}]}]},propDecorators:{minRows:[{type:m,args:["cdkAutosizeMinRows"]}],maxRows:[{type:m,args:["cdkAutosizeMaxRows"]}],enabled:[{type:m,args:["cdkTextareaAutosize"]}],placeholder:[{type:m}]}}); - /** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - class Vr{}Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Vr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,declarations:[wr,Dr],exports:[wr,Dr]}),Vr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,decorators:[{type:d,args:[{declarations:[wr,Dr],exports:[wr,Dr]}]}]});class Pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[O.required]],toTemplate:[e?e.toTemplate:null,[O.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[O.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[O.required]],bodyTemplate:[e?e.bodyTemplate:null,[O.required]]})}prepareInputConfig(e){return{fromTemplate:fe(e?.fromTemplate)?e.fromTemplate:null,toTemplate:fe(e?.toTemplate)?e.toTemplate:null,ccTemplate:fe(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:fe(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:fe(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:fe(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:fe(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:fe(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Pr),Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:de.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Dr,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:te.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:te.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:ne.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Pe.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Pe.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=sn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.copyFrom?ln.METADATA:ln.DATA:fe(e?.copyFrom)?e.copyFrom:ln.DATA,{keys:fe(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=pn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[O.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[O.required]]})}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.fromMetadata?ln.METADATA:ln.DATA:fe(e?.renameIn)?e?.renameIn:ln.DATA,{renameKeysMapping:fe(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Pn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class _r extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[O.required]]})}}e("NodeJsonPathConfigComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n",dependencies:[{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n"}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class Br extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=mn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[O.required]],keys:[e?e.keys:null,[O.required]]})}prepareInputConfig(e){let t;return t=fe(e?.fromMetadata)?e.fromMetadata?ln.METADATA:ln.DATA:fe(e?.deleteFrom)?e?.deleteFrom:ln.DATA,{keys:fe(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[{token:P.Store},{token:R.FormBuilder},{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Br,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:et.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder},{type:Z.TranslateService}]}});class Kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=Ot,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=_t}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[fe(e?.interval)?e.interval:null,[O.required,O.min(1)]],strategy:[fe(e?.strategy)?e.strategy:null,[O.required]],outMsgType:[fe(e?.outMsgType)?e.outMsgType:null,[O.required]],maxPendingMsgs:[fe(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[O.required,O.min(1),O.max(1e3)]],maxRetries:[fe(e?.maxRetries)?e.maxRetries:null,[O.required,O.min(0),O.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:P.Store},{token:R.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:U.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:U.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:J.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Q.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Q.MatLabel,selector:"mat-label"},{kind:"directive",type:Q.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Q.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:re.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:oe.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:oe.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:oe.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:R.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:R.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:Z.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Ae.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Me.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination"]},{kind:"component",type:Kn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:xt,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:P.Store},{type:R.FormBuilder}]}});class zr{}e("RulenodeCoreConfigTransformModule",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),zr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:zr,declarations:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr],imports:[$,M,Jn],exports:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr]}),zr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:d,args:[{declarations:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr],imports:[$,M,Jn],exports:[Ar,Mr,Pr,Rr,Or,_r,Br,Kr]}]}]});class Hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=C}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({forwardMsgToDefaultRuleChain:[!!e&&e?.forwardMsgToDefaultRuleChain,[]],ruleChainId:[e?e.ruleChainId:null,[O.required]]})}}e("RuleChainInputComponent",Hr),Hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hr,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n \n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n \n
\n \n \n
\n
\n',dependencies:[{kind:"component",type:lt.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Y.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:R.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:pe.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
\n
\n
\n \n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n \n
\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class Ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[{token:P.Store},{token:R.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ur,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n',dependencies:[{kind:"directive",type:W.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:R.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:R.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:Z.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
\n
\n
\n'}]}],ctorParameters:function(){return[{type:P.Store},{type:R.UntypedFormBuilder}]}});class jr{}e("RuleNodeCoreConfigFlowModule",jr),jr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),jr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:jr,declarations:[Hr,Ur],imports:[$,M,Jn],exports:[Hr,Ur]}),jr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,imports:[$,M,Jn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,decorators:[{type:d,args:[{declarations:[Hr,Ur],imports:[$,M,Jn],exports:[Hr,Ur]}]}]});class $r{constructor(e){!function(e){e.setTranslation("en_US",{tb:{rulenode:{id:"Id","additional-info":"Additional Info","advanced-settings":"Advanced settings","create-entity-if-not-exists":"Create new entity if it doesn't exist","create-entity-if-not-exists-hint":"If enabled, a new entity with specified parameters will be created unless it already exists. Existing entities will be used as is for relation.","select-device-connectivity-event":"Select device connectivity event","entity-name-pattern":"Name pattern","device-name-pattern":"Device name","asset-name-pattern":"Asset name","entity-view-name-pattern":"Entity view name","customer-title-pattern":"Customer title","dashboard-name-pattern":"Dashboard title","user-name-pattern":"User email","edge-name-pattern":"Edge name","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","copy-message-type":"Copy message type","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","message-type-value":"Message type value","message-type-value-required":"Message type value is required","message-type-value-max-length":"Message type value should be less than 256","output-message-type":"Output message type","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer title","customer-name-pattern-required":"Customer title is required","customer-name-pattern-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","create-customer-if-not-exists":"Create new customer if it doesn't exist","unassign-from-customer":"Unassign from specific customer if originator is dashboard","unassign-from-customer-tooltip":"Only dashboards can be assigned to multiple customers at once. \nIf the message originator is a dashboard, you need to explicitly specify the customer's title to unassign from.","customer-cache-expiration":"Customers cache expiration time (sec)","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","interval-start":"Interval start","interval-end":"Interval end","time-unit":"Time unit","fetch-mode":"Fetch mode","order-by-timestamp":"Order by timestamp",limit:"Limit","limit-hint":"Min limit value is 2, max - 1000. If you want to fetch a single entry, select fetch mode 'First' or 'Last'.","limit-required":"Limit is required.","limit-range":"Limit should be in a range from 2 to 1000.","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Allowing range from 1 to 2147483647.","start-interval-value-required":"Interval start is required.","end-interval-value-required":"Interval end is required.",filter:"Filter",switch:"Switch","math-templatization-tooltip":"This field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","add-message-type":"Add message type","select-message-types-required":"At least one message type should be selected.","select-message-types":"Select message types","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one.","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","attributes-keys":"Attributes keys","attributes-keys-required":"Attributes keys are required","attributes-scope":"Attributes scope","attributes-scope-value":"Attributes scope value","attributes-scope-value-copy":"Copy attributes scope value","attributes-scope-hint":"Use the 'scope' metadata key to dynamically set the attribute scope per message. If provided, this overrides the scope set in the configuration.","notify-device":"Force notification to the device","send-attributes-updated-notification":"Send attributes updated notification","send-attributes-updated-notification-hint":"Send notification about updated attributes as a separate message to the rule engine queue.","send-attributes-deleted-notification":"Send attributes deleted notification","send-attributes-deleted-notification-hint":"Send notification about deleted attributes as a separate message to the rule engine queue.","update-attributes-only-on-value-change":"Save attributes only if the value changes","update-attributes-only-on-value-change-hint":"Updates the attributes on every incoming message disregarding if their value has changed. Increases API usage and reduces performance.","update-attributes-only-on-value-change-hint-enabled":"Updates the attributes only if their value has changed. If the value is not changed, no update to the attribute timestamp nor attribute change notification will be sent.","fetch-credentials-to-metadata":"Fetch credentials to metadata","notify-device-on-update-hint":"If enabled, force notification to the device about shared attributes update. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn off the notification, the message metadata must contain the 'notifyDevice' parameter set to 'false'. Any other case will trigger the notification to the device.","notify-device-on-delete-hint":"If enabled, force notification to the device about shared attributes removal. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn on the notification, the message metadata must contain the 'notifyDevice' parameter set to 'true'. In any other case, the notification will not be triggered to the device.","latest-timeseries":"Latest time series data keys","timeseries-keys":"Time series keys","timeseries-keys-required":"At least one time series key should be selected.","add-timeseries-key":"Add time series key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","relation-parameters":"Relation parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","default-ttl-hint":"Rule node will fetch Time-to-Live (TTL) value from the message metadata. If no value is present, it defaults to the TTL specified in the configuration. If the value is set to 0, the TTL from the tenant profile configuration will be applied.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","reply-routing-configuration":"Reply Routing Configuration","reply-routing-configuration-hint":"These configuration parameters specify the metadata key names used to identify the service and request for sending a reply back.","request-id-metadata-attribute":"Request Id","service-id-metadata-attribute":"Service Id","session-id-metadata-attribute":"Session Id","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-with-specific-entity":"Delete relation with specific entity","delete-relation-with-specific-entity-hint":"If enabled, will delete the relation with just one specific entity. Otherwise, the relation will be removed with all matching entities.","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output time series key prefix","output-timeseries-key-prefix-required":"Output time series key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","add-metadata-key-values-as-kafka-headers":"Add Message metadata key-value pairs to Kafka record headers","add-metadata-key-values-as-kafka-headers-hint":"If selected, key-value pairs from message metadata will be added to the outgoing records headers as byte arrays with predefined charset encoding.","charset-encoding":"Charset encoding","charset-encoding-required":"Charset encoding is required.","charset-us-ascii":"US-ASCII","charset-iso-8859-1":"ISO-8859-1","charset-utf-8":"UTF-8","charset-utf-16be":"UTF-16BE","charset-utf-16le":"UTF-16LE","charset-utf-16":"UTF-16","select-queue-hint":"The queue name can be selected from a drop-down list or add a custom name.","device-profile-node-hint":"Useful if you have duration or repeating conditions to ensure continuity of alarm state evaluation.","persist-alarm-rules":"Persist state of alarm rules","persist-alarm-rules-hint":"If enabled, the rule node will store the state of processing to the database.","fetch-alarm-rules":"Fetch state of alarm rules","fetch-alarm-rules-hint":"If enabled, the rule node will restore the state of processing on initialization and ensure that alarms are raised even after server restarts. Otherwise, the state will be restored when the first message from the device arrives.","input-value-key":"Input value key","input-value-key-required":"Input value key is required.","output-value-key":"Output value key","output-value-key-required":"Output value key is required.","number-of-digits-after-floating-point":"Number of digits after floating point","number-of-digits-after-floating-point-range":"Number of digits after floating point should be in a range from 0 to 15.","failure-if-delta-negative":"Tell Failure if delta is negative","failure-if-delta-negative-tooltip":"Rule node forces failure of message processing if delta value is negative.","use-caching":"Use caching","use-caching-tooltip":'Rule node will cache the value of "{{inputValueKey}}" that arrives from the incoming message to improve performance. Note that the cache will not be updated if you modify the "{{inputValueKey}}" value elsewhere.',"add-time-difference-between-readings":'Add the time difference between "{{inputValueKey}}" readings',"add-time-difference-between-readings-tooltip":'If enabled, the rule node will add the "{{periodValueKey}}" to the outbound message.',"period-value-key":"Period value key","period-value-key-required":"Period value key is required.","general-pattern-hint":"Use ${metadataKey} for value from metadata, $[messageKey] for value from message body.","alarm-severity-pattern-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body. Alarm severity should be system (CRITICAL, MAJOR etc.)',"output-node-name-hint":"The rule node name corresponds to the relation type of the output message, and it is used to forward messages to other rule nodes in the caller rule chain.","skip-latest-persistence":"Skip latest persistence","skip-latest-persistence-hint":"Rule node will not update values for incoming keys for the latest time series data. Useful for highly loaded use-cases to decrease the pressure on the DB.","use-server-ts":"Use server ts","use-server-ts-hint":"Rule node will use the timestamp of message processing instead of the timestamp from the message. Useful for all sorts of sequential processing if you merge messages from multiple sources (devices, assets, etc).","kv-map-pattern-hint":"All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","kv-map-single-pattern-hint":"Input field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","shared-scope":"Shared scope","server-scope":"Server scope","client-scope":"Client scope","attribute-type":"Attribute","constant-type":"Constant","time-series-type":"Time series","message-body-type":"Message","message-metadata-type":"Metadata","argument-tile":"Arguments","no-arguments-prompt":"No arguments configured","result-title":"Result","functions-field-input":"Functions","no-option-found":"No option found","argument-source-field-input":"Source","argument-source-field-input-required":"Argument source is required.","argument-key-field-input":"Key","argument-key-field-input-required":"Argument key is required.","constant-value-field-input":"Constant value","constant-value-field-input-required":"Constant value is required.","attribute-scope-field-input":"Attribute scope","attribute-scope-field-input-required":"Attribute scope os required.","default-value-field-input":"Default value","type-field-input":"Type","type-field-input-required":"Type is required.","key-field-input":"Key","add-entity-type":"Add entity type","add-device-profile":"Add device profile","key-field-input-required":"Key is required.","number-floating-point-field-input":"Number of digits after floating point","number-floating-point-field-input-hint":"Use 0 to convert result to integer","add-to-message-field-input":"Add to message","add-to-metadata-field-input":"Add to metadata","custom-expression-field-input":"Mathematical Expression","custom-expression-field-input-required":"Mathematical expression is required","custom-expression-field-input-hint":"Specify a mathematical expression to evaluate. Default expression demonstrates how to transform Fahrenheit to Celsius","retained-message":"Retained","attributes-mapping":"Attributes mapping","latest-telemetry-mapping":"Latest telemetry mapping","add-mapped-attribute-to":"Add mapped attributes to","add-mapped-latest-telemetry-to":"Add mapped latest telemetry to","add-mapped-fields-to":"Add mapped fields to","add-selected-details-to":"Add selected details to","clear-selected-types":"Clear selected types","clear-selected-details":"Clear selected details","clear-selected-fields":"Clear selected fields","clear-selected-keys":"Clear selected keys","geofence-configuration":"Geofence configuration","coordinate-field-names":"Coordinate field names","coordinate-field-hint":"Rule node tries to retrieve the specified fields from the message. If they are not present, it will look them up in the metadata.","presence-monitoring-strategy":"Presence monitoring strategy","presence-monitoring-strategy-on-first-message":"On first message","presence-monitoring-strategy-on-each-message":"On each message","presence-monitoring-strategy-on-first-message-hint":"Reports presence status 'Inside' or 'Outside' on the first message after the configured minimal duration has passed since previous presence status 'Entered' or 'Left' update.","presence-monitoring-strategy-on-each-message-hint":"Reports presence status 'Inside' or 'Outside' on each message after presence status 'Entered' or 'Left' update.","fetch-credentials-to":"Fetch credentials to","add-originator-attributes-to":"Add originator attributes to","originator-attributes":"Originator attributes","fetch-latest-telemetry-with-timestamp":"Fetch latest telemetry with timestamp","fetch-latest-telemetry-with-timestamp-tooltip":'If selected, latest telemetry values will be added to the outbound metadata with timestamp, e.g: "{{latestTsKeyName}}": "{"ts":1574329385897, "value":42}"',"tell-failure":"Tell failure if any of the attributes are missing","tell-failure-tooltip":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"created-time":"Created time","chip-help":"Press 'Enter' to complete {{inputName}} input. \nPress 'Backspace' to delete {{inputName}}. \nMultiple values supported.",detail:"detail","field-name":"field name","device-profile":"device profile","entity-type":"entity type","message-type":"message type","timeseries-key":"time series key",type:"Type","first-name":"First name","last-name":"Last name",label:"Label","originator-fields-mapping":"Originator fields mapping","add-mapped-originator-fields-to":"Add mapped originator fields to",fields:"Fields","skip-empty-fields":"Skip empty fields","skip-empty-fields-tooltip":"Fields with empty values will not be added to the output message/output metadata.","fetch-interval":"Fetch interval","fetch-strategy":"Fetch strategy","fetch-timeseries-from-to":"Fetch time series from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch time series invalid ("Interval start" should be less than "Interval end").',"use-metadata-dynamic-interval-tooltip":"If selected, the rule node will use dynamic interval start and end based on the message and metadata patterns.","all-mode-hint":'If selected fetch mode "All" rule node will retrieve telemetry from the fetch interval with configurable query parameters.',"first-mode-hint":'If selected fetch mode "First" rule node will retrieve the closest telemetry to the fetch interval\'s start.',"last-mode-hint":'If selected fetch mode "Last" rule node will retrieve the closest telemetry to the fetch interval\'s end.',ascending:"Ascending",descending:"Descending",min:"Min",max:"Max",average:"Average",sum:"Sum",count:"Count",none:"None","last-level-relation-tooltip":"If selected, the rule node will search related entities only on the level set in the max relation level.","last-level-device-relation-tooltip":"If selected, the rule node will search related devices only on the level set in the max relation level.","data-to-fetch":"Data to fetch","mapping-of-customers":"Mapping of customer's","map-fields-required":"All mapping fields are required.",attributes:"Attributes","related-device-attributes":"Related device attributes","add-selected-attributes-to":"Add selected attributes to","device-profiles":"Device profiles","mapping-of-tenant":"Mapping of tenant's","add-attribute-key":"Add attribute key","message-template":"Message template","message-template-required":"Message template is required","use-system-slack-settings":"Use system slack settings","slack-api-token":"Slack API token","slack-api-token-required":"Slack API token is required","keys-mapping":"keys mapping","add-key":"Add key",recipients:"Recipients","message-subject-and-content":"Message subject and content","template-rules-hint":"Both input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the message metadata.","originator-customer-desc":"Use customer of incoming message originator as new originator.","originator-tenant-desc":"Use current tenant as new originator.","originator-related-entity-desc":"Use related entity as new originator. Lookup based on configured relation type and direction.","originator-alarm-originator-desc":"Use alarm originator as new originator. Only if incoming message originator is alarm entity.","originator-entity-by-name-pattern-desc":"Use entity fetched from DB as new originator. Lookup based on entity type and specified name pattern.","email-from-template-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","recipients-block-main-hint":"Comma-separated address list. All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","forward-msg-default-rule-chain":"Forward message to the originator's default rule chain","forward-msg-default-rule-chain-tooltip":"If enabled, message will be forwarded to the originator's default rule chain, or rule chain from configuration, if originator has no default rule chain defined in the entity profile.","exclude-zero-deltas":"Exclude zero deltas from outbound message","exclude-zero-deltas-hint":'If enabled, the "{{outputValueKey}}" output key will be added to the outbound message if its value is not zero.',"exclude-zero-deltas-time-difference-hint":'If enabled, the "{{outputValueKey}}" and "{{periodValueKey}}" output keys will be added to the outbound message only if the "{{outputValueKey}}" value is not zero.',"search-direction-from":"From originator to target entity","search-direction-to":"From target entity to originator","del-relation-direction-from":"From originator","del-relation-direction-to":"To originator","target-entity":"Target entity","function-configuration":"Function configuration","function-name":"Function name","function-name-required":"Function name is required.",qualifier:"Qualifier","qualifier-hint":'If the qualifier is not specified, the default qualifier "$LATEST" will be used.',"aws-credentials":"AWS Credentials","connection-timeout":"Connection timeout","connection-timeout-required":"Connection timeout is required.","connection-timeout-min":"Min connection timeout is 0.","connection-timeout-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception.","request-timeout":"Request timeout","request-timeout-required":"Request timeout is required","request-timeout-min":"Min request timeout is 0","request-timeout-hint":"The amount of time to wait in seconds for the request to complete before giving up and timing out. A value of 0 means infinity, and is not recommended.","tell-failure-aws-lambda":"Tell Failure if AWS Lambda function execution raises exception","tell-failure-aws-lambda-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",$r),$r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,deps:[{token:Z.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),$r.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$r,declarations:[dt],imports:[$,M],exports:[Qn,qr,ir,vr,zr,jr,dt]}),$r.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,imports:[$,M,Qn,qr,ir,vr,zr,jr]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,decorators:[{type:d,args:[{declarations:[dt],imports:[$,M],exports:[Qn,qr,ir,vr,zr,jr,dt]}]}],ctorParameters:function(){return[{type:Z.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map +System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@angular/common","@angular/material/input","@angular/material/form-field","@angular/material/slide-toggle","@angular/flex-layout/flex","@ngx-translate/core","@angular/material/button","@angular/material/icon","@angular/material/select","@angular/material/core","@angular/material/tooltip","@angular/material/expansion","rxjs","@shared/components/hint-tooltip-icon.component","@shared/components/help-popup.component","@shared/pipe/safe.pipe","@core/public-api","@shared/components/js-func.component","@shared/components/script-lang.component","@angular/cdk/keycodes","@angular/material/checkbox","@angular/material/chips","@shared/components/entity/entity-type-select.component","@shared/components/relation/relation-type-autocomplete.component","@shared/components/entity/entity-select.component","@shared/components/toggle-header.component","@shared/components/toggle-select.component","@angular/cdk/coercion","@shared/components/tb-error.component","@angular/flex-layout/extended","@angular/material/list","@angular/cdk/drag-drop","rxjs/operators","@angular/material/autocomplete","@shared/pipe/highlight.pipe","@home/components/public-api","tslib","@shared/components/entity/entity-subtype-list.component","@home/components/relation/relation-filters.component","@shared/components/file-input.component","@shared/components/button/toggle-password.component","@shared/components/string-items-list.component","@shared/components/entity/entity-list.component","@shared/components/notification/template-autocomplete.component","@shared/components/tb-checkbox.component","@home/components/sms/sms-provider-configuration.component","@angular/material/radio","@shared/components/slack-conversation-autocomplete.component","@shared/components/entity/entity-autocomplete.component","@shared/components/entity/entity-type-list.component","@angular/cdk/platform"],(function(e){"use strict";var t,n,r,o,a,i,l,s,m,p,d,u,c,g,f,y,b,x,h,v,C,F,k,T,L,I,S,N,q,A,M,E,w,G,D,V,P,R,O,_,B,K,H,z,U,j,$,J,Q,Y,W,Z,X,ee,te,ne,re,oe,ae,ie,le,se,me,pe,de,ue,ce,ge,fe,ye,be,xe,he,ve,Ce,Fe,ke,Te,Le,Ie,Se,Ne,qe,Ae,Me,Ee,we,Ge,De,Ve,Pe,Re,Oe,_e,Be,Ke,He,ze,Ue,je,$e,Je,Qe,Ye,We,Ze,Xe,et,tt,nt,rt,ot,at,it,lt,st,mt,pt,dt;return{setters:[function(e){t=e,n=e.Component,r=e.InjectionToken,o=e.Injectable,a=e.Inject,i=e.Optional,l=e.EventEmitter,s=e.Directive,m=e.Input,p=e.Output,d=e.NgModule,u=e.ViewChild,c=e.forwardRef},function(e){g=e.RuleNodeConfigurationComponent,f=e.AttributeScope,y=e.telemetryTypeTranslations,b=e.ScriptLanguage,x=e.AlarmSeverity,h=e.alarmSeverityTranslations,v=e.EntitySearchDirection,C=e.EntityType,F=e.AliasEntityType,k=e.entityFields,T=e.PageComponent,L=e.messageTypeNames,I=e.MessageType,S=e.coerceBoolean,N=e.entitySearchDirectionTranslations,q=e,A=e.AlarmStatus,M=e.alarmStatusTranslations,E=e.SharedModule,w=e.AggregationType,G=e.aggregationTranslations,D=e.NotificationType,V=e.SlackChanelType,P=e.SlackChanelTypesTranslateMap},function(e){R=e},function(e){O=e,_=e.Validators,B=e.NgControl,K=e.NG_VALUE_ACCESSOR,H=e.NG_VALIDATORS,z=e.FormArray,U=e.FormGroup},function(e){j=e,$=e.DOCUMENT,J=e.CommonModule},function(e){Q=e},function(e){Y=e},function(e){W=e},function(e){Z=e},function(e){X=e},function(e){ee=e},function(e){te=e},function(e){ne=e},function(e){re=e},function(e){oe=e},function(e){ae=e},function(e){ie=e.Subject,le=e.takeUntil,se=e.of,me=e.EMPTY,pe=e.fromEvent},function(e){de=e},function(e){ue=e},function(e){ce=e},function(e){ge=e.getCurrentAuthState,fe=e,ye=e.isDefinedAndNotNull,be=e.isEqual,xe=e.deepTrim,he=e.isObject,ve=e.isNotEmptyStr},function(e){Ce=e},function(e){Fe=e},function(e){ke=e.ENTER,Te=e.COMMA,Le=e.SEMICOLON},function(e){Ie=e},function(e){Se=e},function(e){Ne=e},function(e){qe=e},function(e){Ae=e},function(e){Me=e},function(e){Ee=e},function(e){we=e.coerceBooleanProperty,Ge=e.coerceElement,De=e.coerceNumberProperty},function(e){Ve=e},function(e){Pe=e},function(e){Re=e},function(e){Oe=e},function(e){_e=e.tap,Be=e.map,Ke=e.startWith,He=e.mergeMap,ze=e.share,Ue=e.takeUntil,je=e.auditTime},function(e){$e=e},function(e){Je=e},function(e){Qe=e.HomeComponentsModule},function(e){Ye=e.__decorate},function(e){We=e},function(e){Ze=e},function(e){Xe=e},function(e){et=e},function(e){tt=e},function(e){nt=e},function(e){rt=e},function(e){ot=e},function(e){at=e},function(e){it=e},function(e){lt=e},function(e){st=e},function(e){mt=e},function(e){pt=e.normalizePassiveListenerOptions,dt=e}],execute:function(){class ut extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}}e("EmptyConfigComponent",ut),ut.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ut.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ut,selector:"tb-node-empty-config",usesInheritance:!0,ngImport:t,template:"
",isInline:!0}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ut,decorators:[{type:n,args:[{selector:"tb-node-empty-config",template:"
"}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class ct extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.assignCustomerConfigForm}onConfigurationSet(e){this.assignCustomerConfigForm=this.fb.group({customerNamePattern:[e?e.customerNamePattern:null,[_.required,_.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}}e("AssignCustomerConfigComponent",ct),ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ct,selector:"tb-action-node-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ct,decorators:[{type:n,args:[{selector:"tb-action-node-assign-to-customer-config",template:'
\n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n \n {{ \'tb.rulenode.create-customer-if-not-exists\' | translate }}\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});const gt=new r("WindowToken","undefined"!=typeof window&&window.document?{providedIn:"root",factory:()=>window}:{providedIn:"root",factory:()=>{}});class ft{constructor(e,t,n){this.ngZone=e,this.document=t,this.window=n,this.copySubject=new ie,this.copyResponse$=this.copySubject.asObservable(),this.config={}}configure(e){this.config=e}copy(e){if(!this.isSupported||!e)return this.pushCopyResponse({isSuccess:!1,content:e});const t=this.copyFromContent(e);return t?this.pushCopyResponse({content:e,isSuccess:t}):this.pushCopyResponse({isSuccess:!1,content:e})}get isSupported(){return!!this.document.queryCommandSupported&&!!this.document.queryCommandSupported("copy")&&!!this.window}isTargetValid(e){if(e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement){if(e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');return!0}throw new Error("Target should be input or textarea")}copyFromInputElement(e,t=!0){try{this.selectTarget(e);const n=this.copyText();return this.clearSelection(t?e:void 0,this.window),n&&this.isCopySuccessInIE11()}catch(e){return!1}}isCopySuccessInIE11(){const e=this.window.clipboardData;return!(e&&e.getData&&!e.getData("Text"))}copyFromContent(e,t=this.document.body){if(this.tempTextArea&&!t.contains(this.tempTextArea)&&this.destroy(this.tempTextArea.parentElement||void 0),!this.tempTextArea){this.tempTextArea=this.createTempTextArea(this.document,this.window);try{t.appendChild(this.tempTextArea)}catch(e){throw new Error("Container should be a Dom element")}}this.tempTextArea.value=e;const n=this.copyFromInputElement(this.tempTextArea,!1);return this.config.cleanUpAfterCopy&&this.destroy(this.tempTextArea.parentElement||void 0),n}destroy(e=this.document.body){this.tempTextArea&&(e.removeChild(this.tempTextArea),this.tempTextArea=void 0)}selectTarget(e){return e.select(),e.setSelectionRange(0,e.value.length),e.value.length}copyText(){return this.document.execCommand("copy")}clearSelection(e,t){e&&e.focus(),t.getSelection()?.removeAllRanges()}createTempTextArea(e,t){const n="rtl"===e.documentElement.getAttribute("dir");let r;r=e.createElement("textarea"),r.style.fontSize="12pt",r.style.border="0",r.style.padding="0",r.style.margin="0",r.style.position="absolute",r.style[n?"right":"left"]="-9999px";const o=t.pageYOffset||e.documentElement.scrollTop;return r.style.top=o+"px",r.setAttribute("readonly",""),r}pushCopyResponse(e){this.copySubject.observers.length>0&&this.ngZone.run((()=>{this.copySubject.next(e)}))}pushCopyReponse(e){this.pushCopyResponse(e)}}ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,deps:[{token:t.NgZone},{token:$},{token:gt,optional:!0}],target:t.ɵɵFactoryTarget.Injectable}),ft.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:ft,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:void 0,decorators:[{type:a,args:[$]}]},{type:void 0,decorators:[{type:i},{type:a,args:[gt]}]}]}});class yt{constructor(e,t,n,r){this.ngZone=e,this.host=t,this.renderer=n,this.clipboardSrv=r,this.cbOnSuccess=new l,this.cbOnError=new l,this.onClick=e=>{this.clipboardSrv.isSupported?this.targetElm&&this.clipboardSrv.isTargetValid(this.targetElm)?this.handleResult(this.clipboardSrv.copyFromInputElement(this.targetElm),this.targetElm.value,e):this.cbContent&&this.handleResult(this.clipboardSrv.copyFromContent(this.cbContent,this.container),this.cbContent,e):this.handleResult(!1,void 0,e)}}ngOnInit(){this.ngZone.runOutsideAngular((()=>{this.clickListener=this.renderer.listen(this.host.nativeElement,"click",this.onClick)}))}ngOnDestroy(){this.clickListener&&this.clickListener(),this.clipboardSrv.destroy(this.container)}handleResult(e,t,n){let r={isSuccess:e,content:t,successMessage:this.cbSuccessMsg,event:n};e?this.cbOnSuccess.observed&&this.ngZone.run((()=>{this.cbOnSuccess.emit(r)})):this.cbOnError.observed&&this.ngZone.run((()=>{this.cbOnError.emit(r)})),this.clipboardSrv.pushCopyResponse(r)}}yt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,deps:[{token:t.NgZone},{token:t.ElementRef},{token:t.Renderer2},{token:ft}],target:t.ɵɵFactoryTarget.Directive}),yt.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:yt,selector:"[ngxClipboard]",inputs:{targetElm:["ngxClipboard","targetElm"],container:"container",cbContent:"cbContent",cbSuccessMsg:"cbSuccessMsg"},outputs:{cbOnSuccess:"cbOnSuccess",cbOnError:"cbOnError"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:yt,decorators:[{type:s,args:[{selector:"[ngxClipboard]"}]}],ctorParameters:function(){return[{type:t.NgZone},{type:t.ElementRef},{type:t.Renderer2},{type:ft}]},propDecorators:{targetElm:[{type:m,args:["ngxClipboard"]}],container:[{type:m}],cbContent:[{type:m}],cbSuccessMsg:[{type:m}],cbOnSuccess:[{type:p}],cbOnError:[{type:p}]}});class bt{constructor(e,t,n){this._clipboardService=e,this._viewContainerRef=t,this._templateRef=n}ngOnInit(){this._clipboardService.isSupported&&this._viewContainerRef.createEmbeddedView(this._templateRef)}}bt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,deps:[{token:ft},{token:t.ViewContainerRef},{token:t.TemplateRef}],target:t.ɵɵFactoryTarget.Directive}),bt.ɵdir=t.ɵɵngDeclareDirective({minVersion:"12.0.0",version:"13.0.1",type:bt,selector:"[ngxClipboardIfSupported]",ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:bt,decorators:[{type:s,args:[{selector:"[ngxClipboardIfSupported]"}]}],ctorParameters:function(){return[{type:ft},{type:t.ViewContainerRef},{type:t.TemplateRef}]}});class xt{}xt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:xt,deps:[],target:t.ɵɵFactoryTarget.NgModule}),xt.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:xt,declarations:[yt,bt],imports:[J],exports:[yt,bt]}),xt.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:xt,imports:[[J]]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"13.0.1",ngImport:t,type:xt,decorators:[{type:d,args:[{imports:[J],declarations:[yt,bt],exports:[yt,bt]}]}]});class ht{constructor(){this.textAlign="left"}}e("ExampleHintComponent",ht),ht.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,deps:[],target:t.ɵɵFactoryTarget.Component}),ht.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ht,selector:"tb-example-hint",inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},ngImport:t,template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ht,decorators:[{type:n,args:[{selector:"tb-example-hint",template:'
\n
\n
\n
\n
\n',styles:[":host .space-between{display:flex;justify-content:space-between;gap:20px}:host .space-between .see-example{display:flex;flex-shrink:0}:host .hint-text{width:100%}\n"]}]}],propDecorators:{hintText:[{type:m}],popupHelpLink:[{type:m}],textAlign:[{type:m}]}});class vt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[_.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===f.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}}e("AttributesConfigComponent",vt),vt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vt,selector:"tb-action-node-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vt,decorators:[{type:n,args:[{selector:"tb-action-node-attributes-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.update-attributes-only-on-value-change\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.send-attributes-updated-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Ct extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.clearAlarmConfigForm}onConfigurationSet(e){this.clearAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[_.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[_.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===b.JS?[_.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===b.TBEL?[_.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",o=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.clearAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.clearAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ClearAlarmConfigComponent",Ct),Ct.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ct.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ct,selector:"tb-action-node-clear-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ct,decorators:[{type:n,args:[{selector:"tb-action-node-clear-alarm-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ft extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.alarmSeverities=Object.keys(x),this.alarmSeverityTranslationMap=h,this.separatorKeysCodes=[ke,Te,Le],this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-details-function"}configForm(){return this.createAlarmConfigForm}onConfigurationSet(e){this.createAlarmConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[_.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],useMessageAlarmData:[!!e&&e.useMessageAlarmData,[]],overwriteAlarmDetails:[!!e&&e.overwriteAlarmDetails,[]],alarmType:[e?e.alarmType:null,[]],severity:[e?e.severity:null,[]],propagate:[!!e&&e.propagate,[]],relationTypes:[e?e.relationTypes:null,[]],propagateToOwner:[!!e&&e.propagateToOwner,[]],propagateToTenant:[!!e&&e.propagateToTenant,[]],dynamicSeverity:!1}),this.createAlarmConfigForm.get("dynamicSeverity").valueChanges.subscribe((e=>{e?this.createAlarmConfigForm.get("severity").patchValue("",{emitEvent:!1}):this.createAlarmConfigForm.get("severity").patchValue(this.alarmSeverities[0],{emitEvent:!1})}))}validatorTriggers(){return["useMessageAlarmData","overwriteAlarmDetails","scriptLang"]}updateValidators(e){const t=this.createAlarmConfigForm.get("useMessageAlarmData").value,n=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;t?(this.createAlarmConfigForm.get("alarmType").setValidators([]),this.createAlarmConfigForm.get("severity").setValidators([])):(this.createAlarmConfigForm.get("alarmType").setValidators([_.required]),this.createAlarmConfigForm.get("severity").setValidators([_.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==b.TBEL||this.tbelEnabled||(r=b.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const o=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(o&&r===b.JS?[_.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(o&&r===b.TBEL?[_.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===b.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===b.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",o=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"json",this.translate.instant("tb.rulenode.details"),"Details",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.createAlarmConfigForm.get(n).setValue(e),this.changeScript.emit())}))}removeKey(e,t){const n=this.createAlarmConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.createAlarmConfigForm.get(t).setValue(n,{emitEvent:!0}))}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.createAlarmConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.createAlarmConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}onValidate(){const e=this.createAlarmConfigForm.get("useMessageAlarmData").value,t=this.createAlarmConfigForm.get("overwriteAlarmDetails").value;if(!e||t){this.createAlarmConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}}e("CreateAlarmConfigComponent",Ft),Ft.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Ft.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ft,selector:"tb-action-node-create-alarm-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Se.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Se.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Se.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Se.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ft,decorators:[{type:n,args:[{selector:"tb-action-node-create-alarm-config",template:'
\n \n {{ \'tb.rulenode.use-message-alarm-data\' | translate }}\n \n \n {{ \'tb.rulenode.overwrite-alarm-details\' | translate }}\n \n
\n \n \n \n \n \n \n \n
\n \n
\n
\n
\n \n tb.rulenode.alarm-type\n \n \n {{ \'tb.rulenode.alarm-type-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-alarm-severity-pattern\' | translate }}\n \n \n tb.rulenode.alarm-severity\n \n \n {{ alarmSeverityTranslationMap.get(severity) | translate }}\n \n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n tb.rulenode.alarm-severity-pattern\n \n \n {{ \'tb.rulenode.alarm-severity-required\' | translate }}\n \n \n \n \n {{ \'tb.rulenode.propagate\' | translate }}\n \n
\n \n tb.rulenode.relation-types-list\n \n \n {{key}}\n close\n \n \n \n tb.rulenode.relation-types-list-hint\n \n
\n \n {{ \'tb.rulenode.propagate-to-owner\' | translate }}\n \n \n {{ \'tb.rulenode.propagate-to-tenant\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class kt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.search-direction-from"],[v.TO,"tb.rulenode.search-direction-to"]]),this.entityType=C,this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[_.required]],entityType:[e?e.entityType:null,[_.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[_.required]],createEntityIfNotExists:[!!e&&e.createEntityIfNotExists,[]],removeCurrentRelations:[!!e&&e.removeCurrentRelations,[]],changeOriginatorToRelatedEntity:[!!e&&e.changeOriginatorToRelatedEntity,[]]})}validatorTriggers(){return["entityType","createEntityIfNotExists"]}updateValidators(e){const t=this.createRelationConfigForm.get("entityType").value;if(t?this.createRelationConfigForm.get("entityNamePattern").setValidators([_.required,_.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==C.DEVICE&&t!==C.ASSET)this.createRelationConfigForm.get("entityTypePattern").setValidators([]);else{const e=[_.pattern(/.*\S.*/)];this.createRelationConfigForm.get("createEntityIfNotExists").value&&e.push(_.required),this.createRelationConfigForm.get("entityTypePattern").setValidators(e)}this.createRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e}),this.createRelationConfigForm.get("entityTypePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e.entityTypePattern=e.entityTypePattern?e.entityTypePattern.trim():null,e}}e("CreateRelationConfigComponent",kt),kt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kt,selector:"tb-action-node-create-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n\n
\n
tb.rulenode.target-entity
\n
\n \n \n\n \n {{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n\n \n tb.rulenode.profile-name\n \n \n
\n\n \n\n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled","additionEntityTypes"]},{kind:"component",type:qe.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kt,decorators:[{type:n,args:[{selector:"tb-action-node-create-relation-config",template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n\n
\n
tb.rulenode.target-entity
\n
\n \n \n\n \n {{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n\n \n tb.rulenode.profile-name\n \n \n
\n\n \n\n
\n \n {{ \'tb.rulenode.create-entity-if-not-exists\' | translate }}\n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n {{ \'tb.rulenode.remove-current-relations\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.change-originator-to-related-entity\' | translate }}\n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Tt extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=new Map([[v.FROM,"tb.rulenode.del-relation-direction-from"],[v.TO,"tb.rulenode.del-relation-direction-to"]]),this.entityTypeNamePatternTranslation=new Map([[C.DEVICE,"tb.rulenode.device-name-pattern"],[C.ASSET,"tb.rulenode.asset-name-pattern"],[C.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[C.CUSTOMER,"tb.rulenode.customer-title-pattern"],[C.USER,"tb.rulenode.user-name-pattern"],[C.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[C.EDGE,"tb.rulenode.edge-name-pattern"]]),this.entityType=C,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.EDGE]}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[_.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[_.required]]})}validatorTriggers(){return["deleteForSingleEntity","entityType"]}updateValidators(e){const t=this.deleteRelationConfigForm.get("deleteForSingleEntity").value,n=this.deleteRelationConfigForm.get("entityType").value;t?this.deleteRelationConfigForm.get("entityType").setValidators([_.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n&&n!==C.TENANT?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([_.required,_.pattern(/.*\S.*/)]):this.deleteRelationConfigForm.get("entityNamePattern").setValidators([]),this.deleteRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:!1}),this.deleteRelationConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return e.entityNamePattern=e.entityNamePattern?e.entityNamePattern.trim():null,e}}e("DeleteRelationConfigComponent",Tt),Tt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tt,selector:"tb-action-node-delete-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n \n
\n
\n
\n \n \n \n {{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n
\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled","additionEntityTypes"]},{kind:"component",type:qe.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tt,decorators:[{type:n,args:[{selector:"tb-action-node-delete-relation-config",template:'
\n
\n
tb.rulenode.relation-parameters
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.delete-relation-with-specific-entity\' | translate }}\n \n
\n
\n
\n \n \n \n {{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get(\'entityType\').value) | translate }}\n \n \n
\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Lt extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.deviceProfile}onConfigurationSet(e){this.deviceProfile=this.fb.group({persistAlarmRulesState:[!!e&&e.persistAlarmRulesState],fetchAlarmRulesStateOnStart:[!!e&&e.fetchAlarmRulesStateOnStart]})}validatorTriggers(){return["persistAlarmRulesState"]}updateValidators(e){this.deviceProfile.get("persistAlarmRulesState").value?this.deviceProfile.get("fetchAlarmRulesStateOnStart").enable({emitEvent:!1}):(this.deviceProfile.get("fetchAlarmRulesStateOnStart").setValue(!1,{emitEvent:!1}),this.deviceProfile.get("fetchAlarmRulesStateOnStart").disable({emitEvent:!1})),this.deviceProfile.get("fetchAlarmRulesStateOnStart").updateValueAndValidity({emitEvent:e})}}e("DeviceProfileConfigComponent",Lt),Lt.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lt.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lt,selector:"tb-device-profile-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.device-profile-node-hint
\n
\n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
\n
\n',dependencies:[{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lt,decorators:[{type:n,args:[{selector:"tb-device-profile-config",template:'
\n
tb.rulenode.device-profile-node-hint
\n
\n \n {{ \'tb.rulenode.persist-alarm-rules\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.fetch-alarm-rules\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class It extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.CUSTOMER,C.USER,C.DASHBOARD,F.CURRENT_TENANT],this.additionEntityTypes={CURRENT_RULE_NODE:this.translate.instant("tb.rulenode.current-rule-node")},this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-generator-function"}configForm(){return this.generatorConfigForm}onConfigurationSet(e){this.generatorConfigForm=this.fb.group({msgCount:[e?e.msgCount:null,[_.required,_.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[_.required,_.min(1)]],originator:[e?e.originator:null,[]],scriptLang:[e?e.scriptLang:b.JS,[_.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS),e.originatorId&&e.originatorType?e.originator={id:e.originatorId,entityType:e.originatorType}:e.originator=null,delete e.originatorId,delete e.originatorType),e}prepareOutputConfig(e){return e.originator?(e.originatorId=e.originator.id,e.originatorType=e.originator.entityType):(e.originatorId=null,e.originatorType=null),delete e.originator,e}testScript(e){const t=this.generatorConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",o=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"generate",this.translate.instant("tb.rulenode.generator"),"Generate",["prevMsg","prevMetadata","prevMsgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.generatorConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.generatorConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}var St;e("GeneratorConfigComponent",It),It.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:It,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),It.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:It,selector:"tb-action-node-generator-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.generation-parameters
\n
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n
\n\n
\n
tb.rulenode.originator
\n \n \n
\n
\n
tb.rulenode.generator-function
\n \n \n \n {{ \'tb.rulenode.script-lang-tbel\' | translate }}\n \n \n {{ \'tb.rulenode.script-lang-js\' | translate }}\n \n \n \n \n \n \n \n {{ \'tb.rulenode.script-lang-tbel\' | translate }}\n \n \n {{ \'tb.rulenode.script-lang-js\' | translate }}\n \n \n \n \n
\n \n
\n
\n
\n',styles:[":host ::ng-deep .mat-button-toggle-group{min-width:120px;height:24px!important}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle{font-size:0}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle .mat-button-toggle-button{height:20px!important;line-height:20px!important;border:none!important}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle .mat-button-toggle-button .mat-button-toggle-label-content{font-size:14px!important;line-height:20px!important}@media screen and (min-width: 599px){:host ::ng-deep .tb-entity-select{display:flex;flex-direction:row;gap:16px}}:host ::ng-deep .tb-entity-select tb-entity-type-select{flex:1}:host ::ng-deep .tb-entity-select tb-entity-autocomplete{flex:1}:host ::ng-deep .tb-entity-select tb-entity-autocomplete mat-form-field{width:100%!important}\n"],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ae.EntitySelectComponent,selector:"tb-entity-select",inputs:["allowedEntityTypes","useAliasEntityTypes","required","disabled","additionEntityTypes"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:It,decorators:[{type:n,args:[{selector:"tb-action-node-generator-config",template:'
\n
\n
tb.rulenode.generation-parameters
\n
\n \n tb.rulenode.message-count\n \n \n {{ \'tb.rulenode.message-count-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-message-count-message\' | translate }}\n \n \n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-seconds-message\' | translate }}\n \n \n
\n
\n\n
\n
tb.rulenode.originator
\n \n \n
\n
\n
tb.rulenode.generator-function
\n \n \n \n {{ \'tb.rulenode.script-lang-tbel\' | translate }}\n \n \n {{ \'tb.rulenode.script-lang-js\' | translate }}\n \n \n \n \n \n \n \n {{ \'tb.rulenode.script-lang-tbel\' | translate }}\n \n \n {{ \'tb.rulenode.script-lang-js\' | translate }}\n \n \n \n \n
\n \n
\n
\n
\n',styles:[":host ::ng-deep .mat-button-toggle-group{min-width:120px;height:24px!important}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle{font-size:0}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle .mat-button-toggle-button{height:20px!important;line-height:20px!important;border:none!important}:host ::ng-deep .mat-button-toggle-group .mat-button-toggle .mat-button-toggle-button .mat-button-toggle-label-content{font-size:14px!important;line-height:20px!important}@media screen and (min-width: 599px){:host ::ng-deep .tb-entity-select{display:flex;flex-direction:row;gap:16px}}:host ::ng-deep .tb-entity-select tb-entity-type-select{flex:1}:host ::ng-deep .tb-entity-select tb-entity-autocomplete{flex:1}:host ::ng-deep .tb-entity-select tb-entity-autocomplete mat-form-field{width:100%!important}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(St||(St={}));const Nt=new Map([[St.CUSTOMER,"tb.rulenode.originator-customer"],[St.TENANT,"tb.rulenode.originator-tenant"],[St.RELATED,"tb.rulenode.originator-related"],[St.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[St.ENTITY,"tb.rulenode.originator-entity"]]),qt=new Map([[St.CUSTOMER,"tb.rulenode.originator-customer-desc"],[St.TENANT,"tb.rulenode.originator-tenant-desc"],[St.RELATED,"tb.rulenode.originator-related-entity-desc"],[St.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[St.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),At=[k.createdTime,k.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},k.firstName,k.lastName,k.email,k.title,k.country,k.state,k.city,k.address,k.address2,k.zip,k.phone,k.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],Mt=new Map([["type","profileName"],["createdTime","createdTime"],["name","name"],["firstName","firstName"],["lastName","lastName"],["email","email"],["title","title"],["country","country"],["state","state"],["city","city"],["address","address"],["address2","address2"],["zip","zip"],["phone","phone"],["label","label"],["id","id"],["additionalInfo","additionalInfo"]]);var Et;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(Et||(Et={}));const wt=new Map([[Et.CIRCLE,"tb.rulenode.perimeter-circle"],[Et.POLYGON,"tb.rulenode.perimeter-polygon"]]);var Gt;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(Gt||(Gt={}));const Dt=new Map([[Gt.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[Gt.SECONDS,"tb.rulenode.time-unit-seconds"],[Gt.MINUTES,"tb.rulenode.time-unit-minutes"],[Gt.HOURS,"tb.rulenode.time-unit-hours"],[Gt.DAYS,"tb.rulenode.time-unit-days"]]);var Vt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(Vt||(Vt={}));const Pt=new Map([[Vt.METER,"tb.rulenode.range-unit-meter"],[Vt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[Vt.FOOT,"tb.rulenode.range-unit-foot"],[Vt.MILE,"tb.rulenode.range-unit-mile"],[Vt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var Rt;!function(e){e.ID="ID",e.TITLE="TITLE",e.COUNTRY="COUNTRY",e.STATE="STATE",e.CITY="CITY",e.ZIP="ZIP",e.ADDRESS="ADDRESS",e.ADDRESS2="ADDRESS2",e.PHONE="PHONE",e.EMAIL="EMAIL",e.ADDITIONAL_INFO="ADDITIONAL_INFO"}(Rt||(Rt={}));const Ot=new Map([[Rt.ID,"tb.rulenode.entity-details-id"],[Rt.TITLE,"tb.rulenode.entity-details-title"],[Rt.COUNTRY,"tb.rulenode.entity-details-country"],[Rt.STATE,"tb.rulenode.entity-details-state"],[Rt.CITY,"tb.rulenode.entity-details-city"],[Rt.ZIP,"tb.rulenode.entity-details-zip"],[Rt.ADDRESS,"tb.rulenode.entity-details-address"],[Rt.ADDRESS2,"tb.rulenode.entity-details-address2"],[Rt.PHONE,"tb.rulenode.entity-details-phone"],[Rt.EMAIL,"tb.rulenode.entity-details-email"],[Rt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var _t;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(_t||(_t={}));const Bt=new Map([[_t.FIRST,"tb.rulenode.first"],[_t.LAST,"tb.rulenode.last"],[_t.ALL,"tb.rulenode.all"]]),Kt=new Map([[_t.FIRST,"tb.rulenode.first-mode-hint"],[_t.LAST,"tb.rulenode.last-mode-hint"],[_t.ALL,"tb.rulenode.all-mode-hint"]]);var Ht,zt;!function(e){e.ASC="ASC",e.DESC="DESC"}(Ht||(Ht={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(zt||(zt={}));const Ut=new Map([[zt.ATTRIBUTES,"tb.rulenode.attributes"],[zt.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[zt.FIELDS,"tb.rulenode.fields"]]),jt=new Map([[zt.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[zt.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[zt.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),$t=new Map([[Ht.ASC,"tb.rulenode.ascending"],[Ht.DESC,"tb.rulenode.descending"]]);var Jt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Jt||(Jt={}));const Qt=new Map([[Jt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Jt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),Yt=["anonymous","basic","cert.PEM"],Wt=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Zt=["sas","cert.PEM"],Xt=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var en;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}(en||(en={}));const tn=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],nn=new Map([["US-ASCII","tb.rulenode.charset-us-ascii"],["ISO-8859-1","tb.rulenode.charset-iso-8859-1"],["UTF-8","tb.rulenode.charset-utf-8"],["UTF-16BE","tb.rulenode.charset-utf-16be"],["UTF-16LE","tb.rulenode.charset-utf-16le"],["UTF-16","tb.rulenode.charset-utf-16"]]);var rn;!function(e){e.CUSTOM="CUSTOM",e.ADD="ADD",e.SUB="SUB",e.MULT="MULT",e.DIV="DIV",e.SIN="SIN",e.SINH="SINH",e.COS="COS",e.COSH="COSH",e.TAN="TAN",e.TANH="TANH",e.ACOS="ACOS",e.ASIN="ASIN",e.ATAN="ATAN",e.ATAN2="ATAN2",e.EXP="EXP",e.EXPM1="EXPM1",e.SQRT="SQRT",e.CBRT="CBRT",e.GET_EXP="GET_EXP",e.HYPOT="HYPOT",e.LOG="LOG",e.LOG10="LOG10",e.LOG1P="LOG1P",e.CEIL="CEIL",e.FLOOR="FLOOR",e.FLOOR_DIV="FLOOR_DIV",e.FLOOR_MOD="FLOOR_MOD",e.ABS="ABS",e.MIN="MIN",e.MAX="MAX",e.POW="POW",e.SIGNUM="SIGNUM",e.RAD="RAD",e.DEG="DEG"}(rn||(rn={}));const on=new Map([[rn.CUSTOM,{value:rn.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[rn.ADD,{value:rn.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[rn.SUB,{value:rn.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[rn.MULT,{value:rn.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[rn.DIV,{value:rn.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[rn.SIN,{value:rn.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[rn.SINH,{value:rn.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[rn.COS,{value:rn.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[rn.COSH,{value:rn.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[rn.TAN,{value:rn.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[rn.TANH,{value:rn.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[rn.ACOS,{value:rn.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[rn.ASIN,{value:rn.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[rn.ATAN,{value:rn.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[rn.ATAN2,{value:rn.ATAN2,name:"2-argument arc tangent",description:"Returns the angle theta from the conversion of rectangular coordinates (x, y) to polar coordinates (r, theta)",minArgs:2,maxArgs:2}],[rn.EXP,{value:rn.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[rn.EXPM1,{value:rn.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[rn.SQRT,{value:rn.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[rn.CBRT,{value:rn.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[rn.GET_EXP,{value:rn.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[rn.HYPOT,{value:rn.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[rn.LOG,{value:rn.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[rn.LOG10,{value:rn.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[rn.LOG1P,{value:rn.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[rn.CEIL,{value:rn.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[rn.FLOOR,{value:rn.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[rn.FLOOR_DIV,{value:rn.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[rn.FLOOR_MOD,{value:rn.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[rn.ABS,{value:rn.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[rn.MIN,{value:rn.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[rn.MAX,{value:rn.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[rn.POW,{value:rn.POW,name:"Raise to a power",description:"Returns the value of the first argument raised to the power of the second argument",minArgs:2,maxArgs:2}],[rn.SIGNUM,{value:rn.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[rn.RAD,{value:rn.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[rn.DEG,{value:rn.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var an,ln,sn;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(an||(an={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(ln||(ln={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(sn||(sn={}));const mn=new Map([[sn.DATA,"tb.rulenode.message-to-metadata"],[sn.METADATA,"tb.rulenode.metadata-to-message"]]),pn=(new Map([[sn.DATA,"tb.rulenode.from-message"],[sn.METADATA,"tb.rulenode.from-metadata"]]),new Map([[sn.DATA,"tb.rulenode.message"],[sn.METADATA,"tb.rulenode.metadata"]])),dn=new Map([[sn.DATA,"tb.rulenode.message"],[sn.METADATA,"tb.rulenode.message-metadata"]]),un=new Map([[an.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[an.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[an.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[an.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[an.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),cn=new Map([[ln.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[ln.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[ln.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[ln.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),gn=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var fn,yn;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(fn||(fn={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(yn||(yn={}));const bn=new Map([[fn.SHARED_SCOPE,"tb.rulenode.shared-scope"],[fn.SERVER_SCOPE,"tb.rulenode.server-scope"],[fn.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var xn;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(xn||(xn={}));const hn=new Map([[xn.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[xn.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]);class vn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Et,this.perimeterTypes=Object.keys(Et),this.perimeterTypeTranslationMap=wt,this.rangeUnits=Object.keys(Vt),this.rangeUnitTranslationMap=Pt,this.presenceMonitoringStrategies=hn,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(Gt),this.timeUnitsTranslationMap=Dt,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[_.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[_.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[_.required]],perimeterType:[e?e.perimeterType:null,[_.required]],fetchPerimeterInfoFromMessageMetadata:[!!e&&e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e?e.perimeterKeyName:null,[]],centerLatitude:[e?e.centerLatitude:null,[]],centerLongitude:[e?e.centerLatitude:null,[]],range:[e?e.range:null,[]],rangeUnit:[e?e.rangeUnit:null,[]],polygonsDefinition:[e?e.polygonsDefinition:null,[]],minInsideDuration:[e?e.minInsideDuration:null,[_.required,_.min(1),_.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[_.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[_.required,_.min(1),_.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[_.required]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoActionConfigForm.get("perimeterType").value;t?this.geoActionConfigForm.get("perimeterKeyName").setValidators([_.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Et.CIRCLE?(this.geoActionConfigForm.get("centerLatitude").setValidators([]),this.geoActionConfigForm.get("centerLongitude").setValidators([]),this.geoActionConfigForm.get("range").setValidators([]),this.geoActionConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoActionConfigForm.get("centerLatitude").setValidators([_.required,_.min(-90),_.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([_.required,_.min(-180),_.max(180)]),this.geoActionConfigForm.get("range").setValidators([_.required,_.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([_.required]),this.defaultPaddingEnable=!1),t||n!==Et.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([_.required]),this.geoActionConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoActionConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoActionConfigComponent",vn),vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vn,selector:"tb-action-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n
\n
\n
{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
\n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
\n
{{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
\n
\n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vn,decorators:[{type:n,args:[{selector:"tb-action-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n
\n \n tb.rulenode.polygon-definition\n \n \n help\n \n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n
\n
\n
{{ \'tb.rulenode.presence-monitoring-strategy\' | translate }}
\n \n \n {{ presenceMonitoringStrategies.get(strategy).name | translate }}\n \n \n
\n
{{ geoActionConfigForm.get(\'reportPresenceStatusOnEachMessage\').value === false ?\n (\'tb.rulenode.presence-monitoring-strategy-on-first-message-hint\' | translate) :\n (\'tb.rulenode.presence-monitoring-strategy-on-each-message-hint\' | translate) }}\n
\n
\n
\n
\n \n tb.rulenode.min-inside-duration\n \n \n {{ \'tb.rulenode.min-inside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-inside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n tb.rulenode.min-outside-duration\n \n \n {{ \'tb.rulenode.min-outside-duration-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n tb.rulenode.min-outside-duration-time-unit\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Cn extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-to-string-function"}configForm(){return this.logConfigForm}onConfigurationSet(e){this.logConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[_.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",o=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"string",this.translate.instant("tb.rulenode.to-string"),"ToString",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.logConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.logConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("LogConfigComponent",Cn),Cn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Cn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Cn,selector:"tb-action-node-log-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cn,decorators:[{type:n,args:[{selector:"tb-action-node-log-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Fn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgCountConfigForm}onConfigurationSet(e){this.msgCountConfigForm=this.fb.group({interval:[e?e.interval:null,[_.required,_.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[_.required]]})}}e("MsgCountConfigComponent",Fn),Fn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fn,selector:"tb-action-node-msg-count-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-count-config",template:'
\n \n tb.rulenode.interval-seconds\n \n \n {{ \'tb.rulenode.interval-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-interval-seconds-message\' | translate }}\n \n \n \n tb.rulenode.output-timeseries-key-prefix\n \n \n {{ \'tb.rulenode.output-timeseries-key-prefix-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class kn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.msgDelayConfigForm}onConfigurationSet(e){this.msgDelayConfigForm=this.fb.group({useMetadataPeriodInSecondsPatterns:[!!e&&e.useMetadataPeriodInSecondsPatterns,[]],periodInSeconds:[e?e.periodInSeconds:null,[]],periodInSecondsPattern:[e?e.periodInSecondsPattern:null,[]],maxPendingMsgs:[e?e.maxPendingMsgs:null,[_.required,_.min(1),_.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([_.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([_.required,_.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}}e("MsgDelayConfigComponent",kn),kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kn,selector:"tb-action-node-msg-delay-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kn,decorators:[{type:n,args:[{selector:"tb-action-node-msg-delay-config",template:'
\n \n {{ \'tb.rulenode.use-metadata-period-in-seconds-patterns\' | translate }}\n \n
tb.rulenode.use-metadata-period-in-seconds-patterns-hint
\n \n tb.rulenode.period-seconds\n \n \n {{ \'tb.rulenode.period-seconds-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-period-0-seconds-message\' | translate }}\n \n \n \n \n tb.rulenode.period-in-seconds-pattern\n \n \n {{ \'tb.rulenode.period-in-seconds-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n \n tb.rulenode.max-pending-messages\n \n \n {{ \'tb.rulenode.max-pending-messages-required\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n {{ \'tb.rulenode.max-pending-messages-range\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Tn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[_.required]]})}}e("PushToCloudConfigComponent",Tn),Tn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tn,selector:"tb-action-node-push-to-cloud-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tn,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-cloud-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Ln extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[_.required]]})}}e("PushToEdgeConfigComponent",Ln),Ln.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ln.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ln,selector:"tb-action-node-push-to-edge-config",usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ln,decorators:[{type:n,args:[{selector:"tb-action-node-push-to-edge-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class In extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcReplyConfigForm}onConfigurationSet(e){this.rpcReplyConfigForm=this.fb.group({serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]],sessionIdMetaDataAttribute:[e?e.sessionIdMetaDataAttribute:null,[]],requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]]})}}e("RpcReplyConfigComponent",In),In.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),In.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:In,selector:"tb-action-node-rpc-reply-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.session-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n',dependencies:[{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:In,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-reply-config",template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.session-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Sn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.rpcRequestConfigForm}onConfigurationSet(e){this.rpcRequestConfigForm=this.fb.group({timeoutInSeconds:[e?e.timeoutInSeconds:null,[_.required,_.min(0)]]})}}e("RpcRequestConfigComponent",Sn),Sn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sn,selector:"tb-action-node-rpc-request-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sn,decorators:[{type:n,args:[{selector:"tb-action-node-rpc-request-config",template:'
\n \n tb.rulenode.timeout-sec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-message\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Nn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.propagateChange=null,this.valueChangeSubscription=null}ngOnInit(){this.ngControl=this.injector.get(B),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({}),this.kvListFormGroup.addControl("keyVals",this.fb.array([]))}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){this.valueChangeSubscription&&this.valueChangeSubscription.unsubscribe();const t=[];if(e)for(const n of Object.keys(e))Object.prototype.hasOwnProperty.call(e,n)&&t.push(this.fb.group({key:[n,[_.required]],value:[e[n],[_.required]]}));this.kvListFormGroup.setControl("keyVals",this.fb.array(t)),this.valueChangeSubscription=this.kvListFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))}removeKeyVal(e){this.kvListFormGroup.get("keyVals").removeAt(e)}addKeyVal(){this.kvListFormGroup.get("keyVals").push(this.fb.group({key:["",[_.required]],value:["",[_.required]]}))}validate(e){const t=this.kvListFormGroup.get("keyVals").value;if(!t.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const e of t)if(e.key===e.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigOldComponent",Nn),Nn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,deps:[{token:R.Store},{token:X.TranslateService},{token:t.Injector},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Nn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nn,selector:"tb-kv-map-config-old",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},providers:[{provide:K,useExisting:c((()=>Nn)),multi:!0},{provide:H,useExisting:c((()=>Nn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ve.TbErrorComponent,selector:"tb-error",inputs:["noMargin","error"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Pe.DefaultShowHideDirective,selector:" [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]",inputs:["fxShow","fxShow.print","fxShow.xs","fxShow.sm","fxShow.md","fxShow.lg","fxShow.xl","fxShow.lt-sm","fxShow.lt-md","fxShow.lt-lg","fxShow.lt-xl","fxShow.gt-xs","fxShow.gt-sm","fxShow.gt-md","fxShow.gt-lg","fxHide","fxHide.print","fxHide.xs","fxHide.sm","fxHide.md","fxHide.lg","fxHide.xl","fxHide.lt-sm","fxHide.lt-md","fxHide.lt-lg","fxHide.lt-xl","fxHide.gt-xs","fxHide.gt-sm","fxHide.gt-md","fxHide.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"pipe",type:j.AsyncPipe,name:"async"},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nn,decorators:[{type:n,args:[{selector:"tb-kv-map-config-old",providers:[{provide:K,useExisting:c((()=>Nn)),multi:!0},{provide:H,useExisting:c((()=>Nn)),multi:!0}],template:'
\n
\n {{ keyText | translate }}\n {{ valText | translate }}\n \n
\n
\n
\n \n \n \n {{ keyRequiredText | translate }}\n \n \n \n \n \n {{ valRequiredText | translate }}\n \n \n \n
\n
\n
\n \n
\n \n
\n
\n',styles:[":host .tb-kv-map-config{margin-bottom:16px}:host .tb-kv-map-config .header{padding-left:5px;padding-right:5px;padding-bottom:5px}:host .tb-kv-map-config .header .cell{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}:host .tb-kv-map-config .header .tb-required:after{color:#757575;font-size:12px;font-weight:700}:host .tb-kv-map-config .body{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}:host .tb-kv-map-config .body .cell{padding-left:5px;padding-right:5px}:host .tb-kv-map-config tb-error{display:block;margin-top:-12px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:t.Injector},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],required:[{type:m}]}});class qn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.saveToCustomTableConfigForm}onConfigurationSet(e){this.saveToCustomTableConfigForm=this.fb.group({tableName:[e?e.tableName:null,[_.required,_.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[_.required]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}}e("SaveToCustomTableConfigComponent",qn),qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),qn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qn,selector:"tb-action-node-custom-table-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qn,decorators:[{type:n,args:[{selector:"tb-action-node-custom-table-config",template:'
\n \n tb.rulenode.custom-table-name\n \n \n {{ \'tb.rulenode.custom-table-name-required\' | translate }}\n \n tb.rulenode.custom-table-hint\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class An extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.timeseriesConfigForm}onConfigurationSet(e){this.timeseriesConfigForm=this.fb.group({defaultTTL:[e?e.defaultTTL:null,[_.required,_.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}}e("TimeseriesConfigComponent",An),An.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),An.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:An,selector:"tb-action-node-timeseries-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.default-ttl\n \n \n help\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:An,decorators:[{type:n,args:[{selector:"tb-action-node-timeseries-config",template:'
\n \n tb.rulenode.default-ttl\n \n \n help\n \n \n {{ \'tb.rulenode.default-ttl-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-default-ttl-message\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.use-server-ts\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.skip-latest-persistence\' | translate }}\n \n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Mn extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}prepareInputConfig(e){return{customerNamePattern:ye(e?.customerNamePattern)?e.customerNamePattern:null,unassignFromCustomer:ye(e?.customerNamePattern)}}onConfigurationSet(e){this.unassignCustomerConfigForm=this.fb.group({customerNamePattern:[e.customerNamePattern,[]],unassignFromCustomer:[e.unassignFromCustomer,[]]})}validatorTriggers(){return["unassignFromCustomer"]}updateValidators(e){this.unassignCustomerConfigForm.get("unassignFromCustomer").value?this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([_.required,_.pattern(/.*\S.*/)]):this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([]),this.unassignCustomerConfigForm.get("customerNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return{customerNamePattern:e.unassignFromCustomer?e.customerNamePattern.trim():null}}}e("UnassignCustomerConfigComponent",Mn),Mn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mn,selector:"tb-action-node-un-assign-to-customer-config",usesInheritance:!0,ngImport:t,template:'
\n
\n\n
\n
\n \n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n \n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n
\n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mn,decorators:[{type:n,args:[{selector:"tb-action-node-un-assign-to-customer-config",template:'
\n
\n\n
\n
\n \n {{ \'tb.rulenode.unassign-from-customer\' | translate }}\n \n
\n \n tb.rulenode.customer-name-pattern\n \n \n {{ \'tb.rulenode.customer-name-pattern-required\' | translate }}\n \n tb.rulenode.customer-name-pattern-hint\n \n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class En extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendRestApiCallReplyConfigForm}onConfigurationSet(e){this.sendRestApiCallReplyConfigForm=this.fb.group({requestIdMetaDataAttribute:[e?e.requestIdMetaDataAttribute:null,[]],serviceIdMetaDataAttribute:[e?e.serviceIdMetaDataAttribute:null,[]]})}}e("SendRestApiCallReplyConfigComponent",En),En.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),En.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:En,selector:"tb-action-node-send-rest-api-call-reply-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n',dependencies:[{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:En,decorators:[{type:n,args:[{selector:"tb-action-node-send-rest-api-call-reply-config",template:'
\n
tb.rulenode.reply-routing-configuration
\n \n \n
\n \n tb.rulenode.service-id-metadata-attribute\n \n \n \n tb.rulenode.request-id-metadata-attribute\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class wn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=f,this.attributeScopes=Object.keys(f),this.telemetryTypeTranslationsMap=y,this.separatorKeysCodes=[ke,Te,Le]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[_.required]],keys:[e?e.keys:null,[_.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==f.SHARED_SCOPE&&this.deleteAttributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1})}))}removeKey(e){const t=this.deleteAttributesConfigForm.get("keys").value,n=t.indexOf(e);n>=0&&(t.splice(n,1),this.deleteAttributesConfigForm.get("keys").patchValue(t,{emitEvent:!0}))}addKey(e){const t=e.input;let n=e.value;if((n||"").trim()){n=n.trim();let e=this.deleteAttributesConfigForm.get("keys").value;e&&-1!==e.indexOf(n)||(e||(e=[]),e.push(n),this.deleteAttributesConfigForm.get("keys").patchValue(e,{emitEvent:!0}))}t&&(t.value="")}}e("DeleteAttributesConfigComponent",wn),wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:wn,selector:"tb-action-node-delete-attributes-config",viewQueries:[{propertyName:"attributeChipList",first:!0,predicate:["attributeChipList"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"component",type:Se.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Se.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Se.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Se.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.NgModel,selector:"[ngModel]:not([formControlName]):not([formControl])",inputs:["name","disabled","ngModel","ngModelOptions"],outputs:["ngModelChange"],exportAs:["ngModel"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:wn,decorators:[{type:n,args:[{selector:"tb-action-node-delete-attributes-config",template:'
\n
\n \n \n
\n \n {{ \'tb.rulenode.attributes-scope\' | translate }}\n \n \n {{ telemetryTypeTranslationsMap.get(scope) | translate }}\n \n \n \n \n {{ \'tb.rulenode.attributes-scope-value\' | translate }}\n \n \n \n
\n
\n\n \n {{ \'tb.rulenode.attributes-keys\' | translate }}\n \n \n {{key}}\n close\n \n \n \n {{ \'tb.rulenode.attributes-keys-required\' | translate }}\n tb.rulenode.general-pattern-hint\n \n\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{ \'tb.rulenode.send-attributes-deleted-notification\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.notify-device\' | translate }}\n \n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]},propDecorators:{attributeChipList:[{type:u,args:["attributeChipList"]}]}});class Gn extends T{get function(){return this.functionValue}set function(e){e&&this.functionValue!==e&&(this.functionValue=e,this.setupArgumentsFormGroup(!0))}constructor(e,t){super(e),this.store=e,this.fb=t,this.maxArgs=16,this.minArgs=1,this.displayArgumentName=!1,this.mathFunctionMap=on,this.ArgumentType=an,this.attributeScopeMap=bn,this.argumentTypeMap=un,this.arguments=Object.values(an),this.attributeScope=Object.values(fn),this.propagateChange=null,this.valueChangeSubscription=[]}ngOnInit(){this.argumentsFormGroup=this.fb.group({arguments:this.fb.array([])}),this.valueChangeSubscription.push(this.argumentsFormGroup.valueChanges.subscribe((()=>{this.updateModel()}))),this.setupArgumentsFormGroup()}onDrop(e){const t=this.argumentsFormArray,n=t.at(e.previousIndex);t.removeAt(e.previousIndex),t.insert(e.currentIndex,n),this.updateArgumentNames()}get argumentsFormArray(){return this.argumentsFormGroup.get("arguments")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.argumentsFormGroup.disable({emitEvent:!1}):(this.argumentsFormGroup.enable({emitEvent:!1}),this.argumentsFormArray.controls.forEach((e=>this.updateArgumentControlValidators(e))))}ngOnDestroy(){this.valueChangeSubscription.length&&this.valueChangeSubscription.forEach((e=>e.unsubscribe()))}writeValue(e){const t=[];e&&e.forEach(((e,n)=>{t.push(this.createArgumentControl(e,n))})),this.argumentsFormGroup.setControl("arguments",this.fb.array(t),{emitEvent:!1}),this.setupArgumentsFormGroup()}removeArgument(e){this.argumentsFormArray.removeAt(e),this.updateArgumentNames()}addArgument(e=!0){const t=this.argumentsFormArray,n=this.createArgumentControl(null,t.length);t.push(n,{emitEvent:e})}validate(e){return this.argumentsFormGroup.valid?null:{argumentsRequired:!0}}setupArgumentsFormGroup(e=!1){if(this.function&&(this.maxArgs=this.mathFunctionMap.get(this.function).maxArgs,this.minArgs=this.mathFunctionMap.get(this.function).minArgs,this.displayArgumentName=this.function===rn.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([_.minLength(this.minArgs),_.maxLength(this.maxArgs)]);this.argumentsFormArray.length>this.maxArgs;)this.removeArgument(this.maxArgs-1);for(;this.argumentsFormArray.length{this.updateArgumentControlValidators(n),n.get("attributeScope").updateValueAndValidity({emitEvent:!1}),n.get("defaultValue").updateValueAndValidity({emitEvent:!1})}))),n}updateArgumentControlValidators(e){const t=e.get("type").value;t===an.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==an.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(gn[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}}e("ArgumentsMapConfigComponent",Gn),Gn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Gn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Gn,selector:"tb-arguments-map-config",inputs:{disabled:"disabled",function:"function"},providers:[{provide:K,useExisting:c((()=>Gn)),multi:!0},{provide:H,useExisting:c((()=>Gn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"],dependencies:[{kind:"directive",type:j.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:ne.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:Re.MatList,selector:"mat-list",exportAs:["matList"]},{kind:"component",type:Re.MatListItem,selector:"mat-list-item, a[mat-list-item], button[mat-list-item]",inputs:["activated"],exportAs:["matListItem"]},{kind:"directive",type:Oe.CdkDropList,selector:"[cdkDropList], cdk-drop-list",inputs:["cdkDropListConnectedTo","cdkDropListData","cdkDropListOrientation","id","cdkDropListLockAxis","cdkDropListDisabled","cdkDropListSortingDisabled","cdkDropListEnterPredicate","cdkDropListSortPredicate","cdkDropListAutoScrollDisabled","cdkDropListAutoScrollStep"],outputs:["cdkDropListDropped","cdkDropListEntered","cdkDropListExited","cdkDropListSorted"],exportAs:["cdkDropList"]},{kind:"directive",type:Oe.CdkDrag,selector:"[cdkDrag]",inputs:["cdkDragData","cdkDragLockAxis","cdkDragRootElement","cdkDragBoundary","cdkDragStartDelay","cdkDragFreeDragPosition","cdkDragDisabled","cdkDragConstrainPosition","cdkDragPreviewClass","cdkDragPreviewContainer"],outputs:["cdkDragStarted","cdkDragReleased","cdkDragEnded","cdkDragEntered","cdkDragExited","cdkDragDropped","cdkDragMoved"],exportAs:["cdkDrag"]},{kind:"directive",type:Oe.CdkDragHandle,selector:"[cdkDragHandle]",inputs:["cdkDragHandleDisabled"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:Pe.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormArrayName,selector:"[formArrayName]",inputs:["formArrayName"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Gn,decorators:[{type:n,args:[{selector:"tb-arguments-map-config",providers:[{provide:K,useExisting:c((()=>Gn)),multi:!0},{provide:H,useExisting:c((()=>Gn)),multi:!0}],template:'
\n\n
\n \n \n
\n \n
\n {{argumentControl.get(\'name\').value}}.\n
\n \n tb.rulenode.argument-source-field-input\n \n \n {{ argumentTypeMap.get(argumentControl.get(\'type\').value)?.name | translate }}\n \n \n {{ argumentTypeMap.get(argument).name | translate }}\n \n {{ argumentTypeMap.get(argument).description }}\n \n \n \n \n tb.rulenode.argument-source-field-input-required\n \n \n
\n \n tb.rulenode.argument-key-field-input\n \n \n help\n \n \n tb.rulenode.argument-key-field-input-required\n \n \n \n tb.rulenode.constant-value-field-input\n \n \n tb.rulenode.constant-value-field-input-required\n \n \n \n tb.rulenode.default-value-field-input\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n tb.rulenode.attribute-scope-field-input-required\n \n \n
\n \n
\n
\n
\n
\n
\n
\n tb.rulenode.no-arguments-prompt\n
\n \n
\n',styles:[":host .mat-mdc-list-item.tb-argument{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}:host .arguments-list{padding:0}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],function:[{type:m}]}});class Dn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.searchText="",this.dirty=!1,this.mathOperation=[...on.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(_e((e=>{let t;t="string"==typeof e&&rn[e]?rn[e]:null,this.updateView(t)})),Be((e=>(this.searchText=e||"",e?this._filter(e):this.mathOperation.slice()))))}_filter(e){const t=e.toLowerCase();return this.mathOperation.filter((e=>e.name.toLowerCase().includes(t)||e.value.toLowerCase().includes(t)))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.mathFunctionForm.disable({emitEvent:!1}):this.mathFunctionForm.enable({emitEvent:!1})}mathFunctionDisplayFn(e){if(e){const t=on.get(e);return t.value+" | "+t.name}return""}writeValue(e){this.modelValue=e,this.mathFunctionForm.get("operation").setValue(e,{emitEvent:!1}),this.dirty=!0}updateView(e){this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}onFocus(){this.dirty&&(this.mathFunctionForm.get("operation").updateValueAndValidity({onlySelf:!0}),this.dirty=!1)}clear(){this.mathFunctionForm.get("operation").patchValue(""),setTimeout((()=>{this.operationInput.nativeElement.blur(),this.operationInput.nativeElement.focus()}),0)}}e("MathFunctionAutocompleteComponent",Dn),Dn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,deps:[{token:R.Store},{token:X.TranslateService},{token:t.Injector},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Dn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Dn,selector:"tb-math-function-autocomplete",inputs:{required:"required",disabled:"disabled"},providers:[{provide:K,useExisting:c((()=>Dn)),multi:!0}],viewQueries:[{propertyName:"operationInput",first:!0,predicate:["operationInput"],descendants:!0,static:!0}],usesInheritance:!0,ngImport:t,template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:$e.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:$e.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:j.AsyncPipe,name:"async"},{kind:"pipe",type:Je.HighlightPipe,name:"highlight"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Dn,decorators:[{type:n,args:[{selector:"tb-math-function-autocomplete",providers:[{provide:K,useExisting:c((()=>Dn)),multi:!0}],template:'\n tb.rulenode.functions-field-input\n \n \n \n \n \n \n {{ option.description }}\n \n \n \n tb.rulenode.no-option-found\n \n \n\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:t.Injector},{type:O.UntypedFormBuilder}]},propDecorators:{required:[{type:m}],disabled:[{type:m}],operationInput:[{type:u,args:["operationInput",{static:!0}]}]}});class Vn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=rn,this.ArgumentTypeResult=ln,this.argumentTypeResultMap=cn,this.attributeScopeMap=bn,this.argumentsResult=Object.values(ln),this.attributeScopeResult=Object.values(yn)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[_.required]],arguments:[e?e.arguments:null,[_.required]],customFunction:[e?e.customFunction:"",[_.required]],result:this.fb.group({type:[e?e.result.type:null,[_.required]],attributeScope:[e?e.result.attributeScope:null,[_.required]],key:[e?e.result.key:"",[_.required]],resultValuePrecision:[e?e.result.resultValuePrecision:0],addToBody:[!!e&&e.result.addToBody],addToMetadata:[!!e&&e.result.addToMetadata]})})}updateValidators(e){const t=this.mathFunctionConfigForm.get("operation").value,n=this.mathFunctionConfigForm.get("result.type").value;t===rn.CUSTOM?(this.mathFunctionConfigForm.get("customFunction").enable({emitEvent:!1}),null===this.mathFunctionConfigForm.get("customFunction").value&&this.mathFunctionConfigForm.get("customFunction").patchValue("(x - 32) / 1.8",{emitEvent:!1})):this.mathFunctionConfigForm.get("customFunction").disable({emitEvent:!1}),n===ln.ATTRIBUTE?this.mathFunctionConfigForm.get("result.attributeScope").enable({emitEvent:!1}):this.mathFunctionConfigForm.get("result.attributeScope").disable({emitEvent:!1}),this.mathFunctionConfigForm.get("customFunction").updateValueAndValidity({emitEvent:e}),this.mathFunctionConfigForm.get("result.attributeScope").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["operation","result.type"]}}e("MathFunctionConfigComponent",Vn),Vn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Vn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Vn,selector:"tb-action-node-math-function-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:ne.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:O.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Gn,selector:"tb-arguments-map-config",inputs:["disabled","function"]},{kind:"component",type:Dn,selector:"tb-math-function-autocomplete",inputs:["required","disabled"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Vn,decorators:[{type:n,args:[{selector:"tb-action-node-math-function-config",template:'
\n \n \n
\n tb.rulenode.argument-tile\n \n \n
\n
\n {{\'tb.rulenode.custom-expression-field-input\' | translate }} *\n \n \n \n tb.rulenode.custom-expression-field-input-required\n \n tb.rulenode.custom-expression-field-input-hint\n \n
\n
\n tb.rulenode.result-title\n
\n \n tb.rulenode.type-field-input\n \n \n {{ argumentTypeResultMap.get(mathFunctionConfigForm.get(\'result.type\').value)?.name | translate }}\n \n \n {{ argumentTypeResultMap.get(argument).name | translate }}\n \n {{ argumentTypeResultMap.get(argument).description }}\n \n \n \n \n tb.rulenode.type-field-input-required\n \n \n
\n \n tb.rulenode.attribute-scope-field-input\n \n \n {{ attributeScopeMap.get(scope) | translate }}\n \n \n \n \n tb.rulenode.key-field-input\n \n help\n \n tb.rulenode.key-field-input-required\n \n \n
\n
\n \n tb.rulenode.number-floating-point-field-input\n \n \n \n
\n
\n \n {{\'tb.rulenode.add-to-message-field-input\' | translate }}\n \n \n {{\'tb.rulenode.add-to-metadata-field-input\' | translate}}\n \n
\n
\n
\n
\n',styles:[":host ::ng-deep .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}:host ::ng-deep .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}:host ::ng-deep .fields-group legend{color:#000000b3;width:-moz-fit-content;width:fit-content}:host ::ng-deep .fields-group legend+*{display:block}:host ::ng-deep .fields-group legend+*.no-margin-top{margin-top:0}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Pn extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=L,this.eventOptions=[I.CONNECT_EVENT,I.ACTIVITY_EVENT,I.DISCONNECT_EVENT,I.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:ye(e?.event)?e.event:I.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[_.required]]})}}e("DeviceStateConfigComponent",Pn),Pn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Pn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Pn,selector:"tb-action-node-device-state-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Pn,decorators:[{type:n,args:[{selector:"tb-action-node-device-state-config",template:'
\n \n {{ \'tb.rulenode.select-device-connectivity-event\' | translate }}\n \n \n {{ messageTypeNames.get(eventOption) }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Rn{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new ie,this.disabled=!1,this.uniqueKeyValuePairValidator=!1,this.required=!1,this.duplicateValuesValidator=e=>e.controls.key.value===e.controls.value.value&&e.controls.key.value&&e.controls.value.value?{uniqueKeyValuePair:!0}:null,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.kvListFormGroup&&this.kvListFormGroup.get("keyVals")&&"VALID"===this.kvListFormGroup.get("keyVals")?.status)return null;const t={};if(this.kvListFormGroup&&this.kvListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return be(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(B),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.kvListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.kvListFormGroup.valueChanges.pipe(le(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.kvListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.kvListFormGroup.disable({emitEvent:!1}):this.kvListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))})),this.kvListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1})}}removeKeyVal(e){this.keyValsFormArray().removeAt(e)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]},{validators:this.uniqueKeyValuePairValidator?[this.duplicateValuesValidator]:[]}))}validate(){const e=this.kvListFormGroup.get("keyVals").value;if(!e.length&&this.required)return{kvMapRequired:!0};if(!this.kvListFormGroup.valid)return{kvFieldsRequired:!0};if(this.uniqueKeyValuePairValidator)for(const t of e)if(t.key===t.value)return{uniqueKeyValuePair:!0};return null}updateModel(){const e=this.kvListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.kvListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("KvMapConfigComponent",Rn),Rn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,deps:[{token:t.Injector},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rn,selector:"tb-kv-map-config",inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",labelText:"labelText",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:K,useExisting:c((()=>Rn)),multi:!0},{provide:H,useExisting:c((()=>Rn)),multi:!0}],ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),Ye([S()],Rn.prototype,"disabled",void 0),Ye([S()],Rn.prototype,"uniqueKeyValuePairValidator",void 0),Ye([S()],Rn.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rn,decorators:[{type:n,args:[{selector:"tb-kv-map-config",providers:[{provide:K,useExisting:c((()=>Rn)),multi:!0},{provide:H,useExisting:c((()=>Rn)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n {{ requiredText }}\n
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ \'tb.key-val.unique-key-value-pair-error\' | translate:\n {\n valText: valText,\n keyText: keyText\n } }}\n
\n
\n
\n
\n
\n
{{ keyText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:t.Injector},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],uniqueKeyValuePairValidator:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],keyText:[{type:m}],keyRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class On extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.entityType=C,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[_.required]],maxLevel:[null,[_.min(1)]],relationType:[null],deviceTypes:[null,[_.required]]}),this.deviceRelationsQueryFormGroup.valueChanges.subscribe((e=>{this.deviceRelationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.deviceRelationsQueryFormGroup.disable({emitEvent:!1}):this.deviceRelationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.deviceRelationsQueryFormGroup.reset(e,{emitEvent:!1})}}e("DeviceRelationsQueryConfigComponent",On),On.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),On.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:On,selector:"tb-device-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:K,useExisting:c((()=>On)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:We.EntitySubTypeListComponent,selector:"tb-entity-subtype-list",inputs:["required","floatLabel","label","disabled","entityType","emptyInputPlaceholder","filledInputPlaceholder","appearance","subscriptSizing","additionalClasses"]},{kind:"component",type:qe.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:On,decorators:[{type:n,args:[{selector:"tb-device-relations-query-config",providers:[{provide:K,useExisting:c((()=>On)),multi:!0}],template:'
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n \n \n help\n \n
\n',styles:[":host .last-level-slide-toggle{margin:8px 0 24px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class _n extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[_.required]],maxLevel:[null,[_.min(1)]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigComponent",_n),_n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),_n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_n,selector:"tb-relations-query-config",inputs:{disabled:"disabled",required:"required"},providers:[{provide:K,useExisting:c((()=>_n)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:Ze.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes","enableNotOption"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_n,decorators:[{type:n,args:[{selector:"tb-relations-query-config",providers:[{provide:K,useExisting:c((()=>_n)),multi:!0}],template:'
\n
tb.rulenode.relations-query
\n
\n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n {{ \'tb.rulenode.max-relation-level-error\' | translate }}\n \n \n
\n
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n
\n
\n
relation.relation-filters
\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class Bn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.truncate=n,this.fb=r,this.placeholder="tb.rulenode.add-message-type",this.separatorKeysCodes=[ke,Te,Le],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(I))this.messageTypesList.push({name:L.get(I[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(Ke(""),Be((e=>e||"")),He((e=>this.fetchMessageTypes(e))),ze())}setDisabledState(e){this.disabled=e,this.disabled?this.messageTypeConfigForm.disable({emitEvent:!1}):this.messageTypeConfigForm.enable({emitEvent:!1})}writeValue(e){this.searchText="",this.messageTypes.length=0,e&&e.forEach((e=>{const t=this.messageTypesList.find((t=>t.value===e));t?this.messageTypes.push({name:t.name,value:t.value}):this.messageTypes.push({name:e,value:e})}))}displayMessageTypeFn(e){return e?e.name:void 0}textIsNotEmpty(e){return e&&e.length>0}createMessageType(e,t){e.preventDefault(),this.transformMessageType(t)}add(e){this.transformMessageType(e.value)}fetchMessageTypes(e){if(this.searchText=e,this.searchText&&this.searchText.length){const e=this.searchText.toUpperCase();return se(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return se(this.messageTypesList)}transformMessageType(e){if((e||"").trim()){let t;const n=e.trim(),r=this.messageTypesList.find((e=>e.name===n));t=r?{name:r.name,value:r.value}:{name:n,value:n},t&&this.addMessageType(t)}this.clear("")}remove(e){const t=this.messageTypes.indexOf(e);t>=0&&(this.messageTypes.splice(t,1),this.updateModel())}selected(e){this.addMessageType(e.option.value),this.clear("")}addMessageType(e){-1===this.messageTypes.findIndex((t=>t.value===e.value))&&(this.messageTypes.push(e),this.updateModel())}onFocus(){this.messageTypeConfigForm.get("messageType").updateValueAndValidity({onlySelf:!0,emitEvent:!0})}clear(e=""){this.messageTypeInput.nativeElement.value=e,this.messageTypeConfigForm.get("messageType").patchValue(null,{emitEvent:!0}),setTimeout((()=>{this.messageTypeInput.nativeElement.blur(),this.messageTypeInput.nativeElement.focus()}),0)}updateModel(){const e=this.messageTypes.map((e=>e.value));this.required?(this.chipList.errorState=!e.length,this.propagateChange(e.length>0?e:null)):(this.chipList.errorState=!1,this.propagateChange(e))}}e("MessageTypesConfigComponent",Bn),Bn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,deps:[{token:R.Store},{token:X.TranslateService},{token:q.TruncatePipe},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Bn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Bn,selector:"tb-message-types-config",inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},providers:[{provide:K,useExisting:c((()=>Bn)),multi:!0}],viewQueries:[{propertyName:"chipList",first:!0,predicate:["chipList"],descendants:!0},{propertyName:"matAutocomplete",first:!0,predicate:["messageTypeAutocomplete"],descendants:!0},{propertyName:"messageTypeInput",first:!0,predicate:["messageTypeInput"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:$e.MatAutocomplete,selector:"mat-autocomplete",inputs:["disableRipple","hideSingleSelectionIndicator"],exportAs:["matAutocomplete"]},{kind:"directive",type:$e.MatAutocompleteTrigger,selector:"input[matAutocomplete], textarea[matAutocomplete]",exportAs:["matAutocompleteTrigger"]},{kind:"directive",type:$e.MatAutocompleteOrigin,selector:"[matAutocompleteOrigin]",exportAs:["matAutocompleteOrigin"]},{kind:"component",type:Se.MatChipGrid,selector:"mat-chip-grid",inputs:["tabIndex","disabled","placeholder","required","value","errorStateMatcher"],outputs:["change","valueChange"]},{kind:"directive",type:Se.MatChipInput,selector:"input[matChipInputFor]",inputs:["matChipInputFor","matChipInputAddOnBlur","matChipInputSeparatorKeyCodes","placeholder","id","disabled"],outputs:["matChipInputTokenEnd"],exportAs:["matChipInput","matChipInputFor"]},{kind:"directive",type:Se.MatChipRemove,selector:"[matChipRemove]"},{kind:"component",type:Se.MatChipRow,selector:"mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]",inputs:["color","disabled","disableRipple","tabIndex","editable"],outputs:["edited"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:j.AsyncPipe,name:"async"},{kind:"pipe",type:Je.HighlightPipe,name:"highlight"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Bn,decorators:[{type:n,args:[{selector:"tb-message-types-config",providers:[{provide:K,useExisting:c((()=>Bn)),multi:!0}],template:'\n {{ label }}\n \n \n {{messageType.name}}\n close\n \n \n \n \n \n \n \n \n
\n
\n tb.rulenode.no-message-types-found\n
\n \n \n {{ \'tb.rulenode.no-message-type-matching\' | translate :\n {messageType: truncate.transform(searchText, true, 6, '...')}\n }}\n \n \n \n tb.rulenode.create-new-message-type\n \n
\n
\n
\n help\n \n {{ \'tb.rulenode.select-message-types-required\' | translate }}\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:q.TruncatePipe},{type:O.FormBuilder}]},propDecorators:{required:[{type:m}],label:[{type:m}],placeholder:[{type:m}],disabled:[{type:m}],chipList:[{type:u,args:["chipList",{static:!1}]}],matAutocomplete:[{type:u,args:["messageTypeAutocomplete",{static:!1}]}],messageTypeInput:[{type:u,args:["messageTypeInput",{static:!1}]}]}});class Kn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=Yt,this.credentialsTypeTranslationsMap=Wt,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[_.required]],username:[null,[]],password:[null,[]],caCert:[null,[]],caCertFileName:[null,[]],privateKey:[null,[]],privateKeyFileName:[null,[]],cert:[null,[]],certFileName:[null,[]]}),this.subscriptions.push(this.credentialsConfigFormGroup.valueChanges.subscribe((()=>{this.updateView()}))),this.subscriptions.push(this.credentialsConfigFormGroup.get("type").valueChanges.subscribe((()=>{this.credentialsTypeChanged()})))}ngOnChanges(e){for(const t of Object.keys(e)){const n=e[t];if(!n.firstChange&&n.currentValue!==n.previousValue&&n.currentValue&&"disableCertPemCredentials"===t){"cert.PEM"===this.credentialsConfigFormGroup.get("type").value&&setTimeout((()=>{this.credentialsConfigFormGroup.get("type").patchValue("anonymous",{emitEvent:!0})}))}}}ngOnDestroy(){this.subscriptions.forEach((e=>e.unsubscribe()))}writeValue(e){ye(e)&&(this.credentialsConfigFormGroup.reset(e,{emitEvent:!1}),this.updateValidators())}setDisabledState(e){e?this.credentialsConfigFormGroup.disable({emitEvent:!1}):(this.credentialsConfigFormGroup.enable({emitEvent:!1}),this.updateValidators())}updateView(){let e=this.credentialsConfigFormGroup.value;const t=e.type;switch(t){case"anonymous":e={type:t};break;case"basic":e={type:t,username:e.username,password:e.password};break;case"cert.PEM":delete e.username}this.propagateChange(e)}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}validate(e){return this.credentialsConfigFormGroup.valid?null:{credentialsConfig:{valid:!1}}}credentialsTypeChanged(){this.credentialsConfigFormGroup.patchValue({username:null,password:null,caCert:null,caCertFileName:null,privateKey:null,privateKeyFileName:null,cert:null,certFileName:null}),this.updateValidators()}updateValidators(e=!1){const t=this.credentialsConfigFormGroup.get("type").value;switch(e&&this.credentialsConfigFormGroup.reset({type:t},{emitEvent:!1}),this.credentialsConfigFormGroup.setValidators([]),this.credentialsConfigFormGroup.get("username").setValidators([]),this.credentialsConfigFormGroup.get("password").setValidators([]),t){case"anonymous":break;case"basic":this.credentialsConfigFormGroup.get("username").setValidators([_.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[_.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(_.required,[["caCert","caCertFileName"],["privateKey","privateKeyFileName","cert","certFileName"]])])}this.credentialsConfigFormGroup.get("username").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.get("password").updateValueAndValidity({emitEvent:e}),this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent:e})}requiredFilesSelected(e,t=null){return n=>{t||(t=[Object.keys(n.controls)]);return n?.controls&&t.some((t=>t.every((t=>!e(n.controls[t])))))?null:{notAllRequiredFilesSelected:!0}}}}e("CredentialsConfigComponent",Kn),Kn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Kn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kn,selector:"tb-credentials-config",inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},providers:[{provide:K,useExisting:c((()=>Kn)),multi:!0},{provide:H,useExisting:c((()=>Kn)),multi:!0}],usesInheritance:!0,usesOnChanges:!0,ngImport:t,template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:j.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:j.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:ae.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:ae.MatExpansionPanelContent,selector:"ng-template[matExpansionPanelContent]"},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Xe.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:et.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kn,decorators:[{type:n,args:[{selector:"tb-credentials-config",providers:[{provide:K,useExisting:c((()=>Kn)),multi:!0},{provide:H,useExisting:c((()=>Kn)),multi:!0}],template:'
\n \n \n tb.rulenode.credentials\n \n {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get(\'type\').value) | translate }}\n \n \n \n \n tb.rulenode.credentials-type\n \n \n {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.username\n \n \n {{ \'tb.rulenode.username-required\' | translate }}\n \n \n \n tb.rulenode.password\n \n \n \n {{ \'tb.rulenode.password-required\' | translate }}\n \n \n \n \n
{{ \'tb.rulenode.credentials-pem-hint\' | translate }}
\n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n
\n
\n
\n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{required:[{type:m}],disableCertPemCredentials:[{type:m}],passwordFieldRequired:[{type:m}]}});class Hn{set required(e){this.requiredValue!==e&&(this.requiredValue=e,this.updateValidators())}get required(){return this.requiredValue}constructor(e){this.fb=e,this.subscriptSizing="fixed",this.messageTypes=[{name:"Post attributes",value:"POST_ATTRIBUTES_REQUEST"},{name:"Post telemetry",value:"POST_TELEMETRY_REQUEST"},{name:"Custom",value:""}],this.propagateChange=()=>{},this.destroy$=new ie,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[_.required]],messageType:[{value:null,disabled:!0},[_.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(le(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(le(this.destroy$)).subscribe((()=>this.updateView()))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}registerOnTouched(e){}registerOnChange(e){this.propagateChange=e}writeValue(e){this.modelValue=e;let t=this.messageTypes.find((t=>t.value===e));t||(t=this.messageTypes.find((e=>""===e.value))),this.messageTypeFormGroup.get("messageTypeAlias").patchValue(t,{emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e,{emitEvent:!1})}validate(){return this.messageTypeFormGroup.valid?null:{messageTypeInvalid:!0}}setDisabledState(e){this.disabled=e,e?this.messageTypeFormGroup.disable({emitEvent:!1}):(this.messageTypeFormGroup.enable({emitEvent:!1}),"Custom"!==this.messageTypeFormGroup.get("messageTypeAlias").value?.name&&this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}))}updateView(){const e=this.messageTypeFormGroup.getRawValue().messageType;this.modelValue!==e&&(this.modelValue=e,this.propagateChange(this.modelValue))}updateValidators(){this.messageTypeFormGroup.get("messageType").setValidators(this.required?[_.required,_.maxLength(255)]:[_.maxLength(255)]),this.messageTypeFormGroup.get("messageType").updateValueAndValidity({emitEvent:!1})}updateMessageTypeValue(e){"Custom"!==e?.name?this.messageTypeFormGroup.get("messageType").disable({emitEvent:!1}):this.messageTypeFormGroup.get("messageType").enable({emitEvent:!1}),this.messageTypeFormGroup.get("messageType").patchValue(e.value??null)}}e("OutputMessageTypeAutocompleteComponent",Hn),Hn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,deps:[{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hn,selector:"tb-output-message-type-autocomplete",inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},providers:[{provide:K,useExisting:c((()=>Hn)),multi:!0},{provide:H,useExisting:c((()=>Hn)),multi:!0}],ngImport:t,template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:yt,selector:"[ngxClipboard]",inputs:["ngxClipboard","container","cbContent","cbSuccessMsg"],outputs:["cbOnSuccess","cbOnError"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),Ye([S()],Hn.prototype,"disabled",void 0),Ye([S()],Hn.prototype,"required",null),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hn,decorators:[{type:n,args:[{selector:"tb-output-message-type-autocomplete",providers:[{provide:K,useExisting:c((()=>Hn)),multi:!0},{provide:H,useExisting:c((()=>Hn)),multi:!0}],template:'
\n \n {{\'tb.rulenode.output-message-type\' | translate}}\n \n \n {{msgType.name}}\n \n \n \n \n {{\'tb.rulenode.message-type-value\' | translate}}\n \n \n \n {{ \'tb.rulenode.message-type-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.message-type-value-max-length\' | translate }}\n \n \n
\n\n'}]}],ctorParameters:function(){return[{type:O.FormBuilder}]},propDecorators:{subscriptSizing:[{type:m}],disabled:[{type:m}],required:[{type:m}]}});class zn{constructor(e,t){this.fb=e,this.translate=t,this.translation=pn,this.propagateChange=()=>{},this.destroy$=new ie,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(Ue(this.destroy$)).subscribe((e=>{e&&this.propagateChange(e)}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}initOptions(){for(const e of this.translation.keys())this.selectOptions.push({value:e,name:this.translate.instant(this.translation.get(e))})}writeValue(e){this.chipControlGroup.get("chipControl").patchValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){e?this.chipControlGroup.disable({emitEvent:!1}):this.chipControlGroup.enable({emitEvent:!1})}}e("MsgMetadataChipComponent",zn),zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,deps:[{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:zn,selector:"tb-msg-metadata-chip",inputs:{labelText:"labelText",translation:"translation"},providers:[{provide:K,useExisting:c((()=>zn)),multi:!0}],ngImport:t,template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Se.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Se.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zn,decorators:[{type:n,args:[{selector:"tb-msg-metadata-chip",providers:[{provide:K,useExisting:c((()=>zn)),multi:!0}],template:'
\n
{{ labelText }}
\n \n {{ option.name }}\n \n
\n'}]}],ctorParameters:function(){return[{type:O.FormBuilder},{type:X.TranslateService}]},propDecorators:{labelText:[{type:m}],translation:[{type:m}]}});class Un extends T{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new ie,this.sourceFieldSubcritption=[],this.propagateChange=null,this.disabled=!1,this.required=!1,this.oneMapRequiredValidator=e=>e.get("keyVals").value.length,this.propagateNestedErrors=e=>{if(this.svListFormGroup&&this.svListFormGroup.get("keyVals")&&"VALID"===this.svListFormGroup.get("keyVals")?.status)return null;const t={};if(this.svListFormGroup&&this.svListFormGroup.setErrors(null),e instanceof z||e instanceof U){if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;for(const n of Object.keys(e.controls)){const r=this.propagateNestedErrors(e.controls[n]);if(r&&Object.keys(r).length)for(const e of Object.keys(r))t[e]=!0}return t}if(e.errors)for(const n of Object.keys(e.errors))t[n]=!0;return be(t,{})?null:t}}ngOnInit(){this.ngControl=this.injector.get(B),null!=this.ngControl&&(this.ngControl.valueAccessor=this),this.svListFormGroup=this.fb.group({keyVals:this.fb.array([])},{validators:[this.propagateNestedErrors,this.oneMapRequiredValidator]}),this.svListFormGroup.valueChanges.pipe(Ue(this.destroy$)).subscribe((()=>{this.updateModel()}))}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}keyValsFormArray(){return this.svListFormGroup.get("keyVals")}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.svListFormGroup.disable({emitEvent:!1}):this.svListFormGroup.enable({emitEvent:!1})}writeValue(e){const t=Object.keys(e).map((t=>({key:t,value:e[t]})));if(this.keyValsFormArray().length===t.length)this.keyValsFormArray().patchValue(t,{emitEvent:!1});else{const e=[];t.forEach((t=>{e.push(this.fb.group({key:[t.key,[_.required]],value:[t.value,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]}))})),this.svListFormGroup.setControl("keyVals",this.fb.array(e,this.propagateNestedErrors),{emitEvent:!1});for(const e of this.keyValsFormArray().controls)this.keyChangeSubscribe(e)}}filterSelectOptions(e){const t=[];for(const e of this.svListFormGroup.get("keyVals").value){const n=this.selectOptions.find((t=>t.value===e.key));n&&t.push(n)}const n=[];for(const r of this.selectOptions)ye(t.find((e=>e.value===r.value)))&&r.value!==e?.get("key").value||n.push(r);return n}removeKeyVal(e){this.keyValsFormArray().removeAt(e),this.sourceFieldSubcritption[e].unsubscribe(),this.sourceFieldSubcritption.splice(e,1)}addKeyVal(){this.keyValsFormArray().push(this.fb.group({key:["",[_.required]],value:["",[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(Ue(this.destroy$)).subscribe((t=>{const n=Mt.get(t);e.get("value").patchValue(this.targetKeyPrefix+n[0].toUpperCase()+n.slice(1))})))}validate(e){return!this.svListFormGroup.get("keyVals").value.length&&this.required?{svMapRequired:!0}:this.svListFormGroup.valid?null:{svFieldsRequired:!0}}updateModel(){const e=this.svListFormGroup.get("keyVals").value;if(this.required&&!e.length||!this.svListFormGroup.valid)this.propagateChange(null);else{const t={};e.forEach((e=>{t[e.key]=e.value})),this.propagateChange(t)}}}e("SvMapConfigComponent",Un),Un.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,deps:[{token:R.Store},{token:X.TranslateService},{token:t.Injector},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Un.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Un,selector:"tb-sv-map-config",inputs:{selectOptions:"selectOptions",disabled:"disabled",labelText:"labelText",requiredText:"requiredText",targetKeyPrefix:"targetKeyPrefix",selectText:"selectText",selectRequiredText:"selectRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",popupHelpLink:"popupHelpLink",required:"required"},providers:[{provide:K,useExisting:c((()=>Un)),multi:!0},{provide:H,useExisting:c((()=>Un)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgClass,selector:"[ngClass]",inputs:["class","ngClass"]},{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Pe.DefaultClassDirective,selector:" [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]",inputs:["ngClass","ngClass.xs","ngClass.sm","ngClass.md","ngClass.lg","ngClass.xl","ngClass.lt-sm","ngClass.lt-md","ngClass.lt-lg","ngClass.lt-xl","ngClass.gt-xs","ngClass.gt-sm","ngClass.gt-md","ngClass.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormControlDirective,selector:"[formControl]",inputs:["formControl","disabled","ngModel"],outputs:["ngModelChange"],exportAs:["ngForm"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:j.AsyncPipe,name:"async"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),Ye([S()],Un.prototype,"disabled",void 0),Ye([S()],Un.prototype,"required",void 0),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Un,decorators:[{type:n,args:[{selector:"tb-sv-map-config",providers:[{provide:K,useExisting:c((()=>Un)),multi:!0},{provide:H,useExisting:c((()=>Un)),multi:!0}],template:'
\n
\n
{{ labelText }}
\n
\n tb.rulenode.map-fields-required\n
\n
\n {{ requiredText }}\n
\n
\n
\n
\n
\n
{{ selectText }}
\n
{{ valText }}
\n
\n
\n
\n
\n \n \n \n {{option.name}}\n \n \n \n \n \n \n
\n \n
\n
\n
\n
\n
\n
\n \n
\n \n
\n',styles:[":host .field-space{flex:1 1 50%}:host .actions-header{width:40px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:t.Injector},{type:O.FormBuilder}]},propDecorators:{selectOptions:[{type:m}],disabled:[{type:m}],labelText:[{type:m}],requiredText:[{type:m}],targetKeyPrefix:[{type:m}],selectText:[{type:m}],selectRequiredText:[{type:m}],valText:[{type:m}],valRequiredText:[{type:m}],hintText:[{type:m}],popupHelpLink:[{type:m}],required:[{type:m}]}});class jn extends T{get required(){return this.requiredValue}set required(e){this.requiredValue=we(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(v),this.directionTypeTranslations=N,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[_.required]],maxLevel:[null,[]],filters:[null]}),this.relationsQueryFormGroup.valueChanges.subscribe((e=>{this.relationsQueryFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}))}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}setDisabledState(e){this.disabled=e,this.disabled?this.relationsQueryFormGroup.disable({emitEvent:!1}):this.relationsQueryFormGroup.enable({emitEvent:!1})}writeValue(e){this.relationsQueryFormGroup.reset(e||{},{emitEvent:!1})}}e("RelationsQueryConfigOldComponent",jn),jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jn,selector:"tb-relations-query-config-old",inputs:{disabled:"disabled",required:"required"},providers:[{provide:K,useExisting:c((()=>jn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Ze.RelationFiltersComponent,selector:"tb-relation-filters",inputs:["disabled","allowedEntityTypes","enableNotOption"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jn,decorators:[{type:n,args:[{selector:"tb-relations-query-config-old",providers:[{provide:K,useExisting:c((()=>jn)),multi:!0}],template:'
\n \n {{ \'alias.last-level-relation\' | translate }}\n \n
\n \n relation.direction\n \n \n {{ directionTypeTranslations.get(type) | translate }}\n \n \n \n \n tb.rulenode.max-relation-level\n \n \n
\n
relation.relation-filters
\n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]},propDecorators:{disabled:[{type:m}],required:[{type:m}]}});class $n{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new ie,this.separatorKeysCodes=[ke,Te,Le],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(_.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(Ue(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||ye(e[n])?e[n]:[];return t}validate(){return this.attributeControlGroup.valid?null:{atLeastOneRequired:!0}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}writeValue(e){this.attributeControlGroup.setValue(e,{emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){this.onTouched=e}setDisabledState(e){e?this.attributeControlGroup.disable({emitEvent:!1}):this.attributeControlGroup.enable({emitEvent:!1})}ngOnDestroy(){this.destroy$.next(null),this.destroy$.complete()}}e("SelectAttributesComponent",$n),$n.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,deps:[{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),$n.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:$n,selector:"tb-select-attributes",inputs:{popupHelpLink:"popupHelpLink"},providers:[{provide:K,useExisting:c((()=>$n)),multi:!0},{provide:H,useExisting:$n,multi:!0}],ngImport:t,template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:j.NgTemplateOutlet,selector:"[ngTemplateOutlet]",inputs:["ngTemplateOutletContext","ngTemplateOutlet","ngTemplateOutletInjector"]},{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$n,decorators:[{type:n,args:[{selector:"tb-select-attributes",providers:[{provide:K,useExisting:c((()=>$n)),multi:!0},{provide:H,useExisting:$n,multi:!0}],template:'
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n {{ \'tb.rulenode.fetch-latest-telemetry-with-timestamp\' | translate }}\n \n
\n
\n\n\n help\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:X.TranslateService},{type:O.FormBuilder}]},propDecorators:{popupHelpLink:[{type:m}]}});class Jn extends T{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new ie,this.alarmStatus=A,this.alarmStatusTranslations=M}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(Ue(this.destroy$)).subscribe((e=>{this.propagateChange(e)}))}setDisabledState(e){e?this.alarmStatusGroup.disable({emitEvent:!1}):this.alarmStatusGroup.enable({emitEvent:!1})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnDestroy(){this.destroy$.next(),this.destroy$.complete()}writeValue(e){this.alarmStatusGroup.get("alarmStatus").patchValue(e,{emitEvent:!1})}}e("AlarmStatusSelectComponent",Jn),Jn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Jn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Jn,selector:"tb-alarm-status-select",providers:[{provide:K,useExisting:c((()=>Jn)),multi:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"],dependencies:[{kind:"component",type:Se.MatChipListbox,selector:"mat-chip-listbox",inputs:["tabIndex","multiple","aria-orientation","selectable","compareWith","required","hideSingleSelectionIndicator","value"],outputs:["change"]},{kind:"component",type:Se.MatChipOption,selector:"mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]",inputs:["color","disabled","disableRipple","tabIndex","selectable","selected"],outputs:["selectionChange"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jn,decorators:[{type:n,args:[{selector:"tb-alarm-status-select",providers:[{provide:K,useExisting:c((()=>Jn)),multi:!0}],template:'
\n \n
\n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }}\n \n
\n
\n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }}\n \n \n {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }}\n \n
\n
\n
\n',styles:[":host .chip-listbox{max-width:460px;width:100%}:host .chip-listbox .toggle-column{display:flex;flex:1 1 100%;gap:8px}:host .chip-listbox .option{margin:0}@media screen and (max-width: 959px){:host .chip-listbox{max-width:360px}:host .chip-listbox .toggle-column{flex-direction:column}}:host ::ng-deep .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}:host ::ng-deep .chip-listbox .option button{flex-basis:100%;justify-content:start}:host ::ng-deep .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Qn{}e("RulenodeCoreConfigCommonModule",Qn),Qn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Qn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Qn,declarations:[Rn,On,_n,Bn,Kn,Gn,Dn,Hn,Nn,zn,Un,jn,$n,Jn,ht],imports:[J,E,Qe],exports:[Rn,On,_n,Bn,Kn,Gn,Dn,Hn,Nn,zn,Un,jn,$n,Jn,ht]}),Qn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,imports:[J,E,Qe]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Qn,decorators:[{type:d,args:[{declarations:[Rn,On,_n,Bn,Kn,Gn,Dn,Hn,Nn,zn,Un,jn,$n,Jn,ht],imports:[J,E,Qe],exports:[Rn,On,_n,Bn,Kn,Gn,Dn,Hn,Nn,zn,Un,jn,$n,Jn,ht]}]}]});class Yn{}e("RuleNodeCoreConfigActionModule",Yn),Yn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Yn.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Yn,declarations:[wn,vt,An,Sn,Cn,ct,Ct,Ft,kt,kn,Tt,It,vn,Fn,In,qn,Mn,En,Lt,Ln,Tn,Vn,Pn],imports:[J,E,Qe,Qn],exports:[wn,vt,An,Sn,Cn,ct,Ct,Ft,kt,kn,Tt,It,vn,Fn,In,qn,Mn,En,Lt,Ln,Tn,Vn,Pn]}),Yn.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,imports:[J,E,Qe,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Yn,decorators:[{type:d,args:[{declarations:[wn,vt,An,Sn,Cn,ct,Ct,Ft,kt,kn,Tt,It,vn,Fn,In,qn,Mn,En,Lt,Ln,Tn,Vn,Pn],imports:[J,E,Qe,Qn],exports:[wn,vt,An,Sn,Cn,ct,Ct,Ft,kt,kn,Tt,It,vn,Fn,In,qn,Mn,En,Lt,Ln,Tn,Vn,Pn]}]}]});class Wn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ke,Te,Le]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[_.min(0),_.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]],excludeZeroDeltas:[e.excludeZeroDeltas,[]]})}prepareInputConfig(e){return{inputValueKey:ye(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:ye(e?.outputValueKey)?e.outputValueKey:null,useCache:!ye(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!ye(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:ye(e?.periodValueKey)?e.periodValueKey:null,round:ye(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!ye(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative,excludeZeroDeltas:!!ye(e?.excludeZeroDeltas)&&e.excludeZeroDeltas}}prepareOutputConfig(e){return xe(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([_.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}}e("CalculateDeltaConfigComponent",Wn),Wn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Wn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Wn,selector:"tb-enrichment-node-calculate-delta-config",usesInheritance:!0,ngImport:t,template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n \n
\n
\n
\n",dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Wn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-calculate-delta-config",template:"
\n
\n \n {{ 'tb.rulenode.input-value-key' | translate }}\n \n \n {{ 'tb.rulenode.input-value-key-required' | translate }}\n \n \n \n {{ 'tb.rulenode.output-value-key' | translate }}\n \n \n {{ 'tb.rulenode.output-value-key-required' | translate }}\n \n \n
\n \n {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.failure-if-delta-negative' | translate }}\n \n
\n
\n \n {{ 'tb.rulenode.use-caching' | translate }}\n \n
\n
\n
\n \n {{ 'tb.rulenode.add-time-difference-between-readings' | translate:\n { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ?\n calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }}\n \n
\n \n {{ 'tb.rulenode.period-value-key' | translate }}\n \n \n {{ 'tb.rulenode.period-value-key-required' | translate }}\n \n \n
\n
\n \n {{ 'tb.rulenode.exclude-zero-deltas' | translate }}\n \n
\n
\n
\n"}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class Zn extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ut.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ut.get(e))})}configForm(){return this.customerAttributesConfigForm}prepareOutputConfig(e){const t={};for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,xe(e)}prepareInputConfig(e){let t,n;return t=ye(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:ye(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=ye(e?.attrMapping)?e.attrMapping:ye(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[_.required]],fetchTo:[e.fetchTo]})}}e("CustomerAttributesConfigComponent",Zn),Zn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Zn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Zn,selector:"tb-enrichment-node-customer-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Rn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Zn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-customer-attributes-config",template:'
\n
tb.rulenode.mapping-of-customers
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class Xn extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.deviceAttributesConfigForm}onConfigurationSet(e){this.deviceAttributesConfigForm=this.fb.group({deviceRelationsQuery:[e.deviceRelationsQuery,[_.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return he(e)&&(e.attributesControl={clientAttributeNames:ye(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ye(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ye(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ye(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ye(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:ye(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!ye(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA,attributesControl:e?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("DeviceAttributesConfigComponent",Xn),Xn.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Xn.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Xn,selector:"tb-enrichment-node-device-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:On,selector:"tb-device-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:$n,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Xn,decorators:[{type:n,args:[{selector:"tb-enrichment-node-device-attributes-config",template:'
\n
\n
tb.rulenode.device-relations-query
\n \n \n
\n
\n
\n
tb.rulenode.related-device-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class er extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(Rt))this.predefinedValues.push({value:Rt[e],name:this.translate.instant(Ot.get(Rt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=ye(e?.addToMetadata)?e.addToMetadata?sn.METADATA:sn.DATA:e?.fetchTo?e.fetchTo:sn.DATA,{detailsList:ye(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[_.required]],fetchTo:[e.fetchTo,[]]})}}e("EntityDetailsConfigComponent",er),er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:er,selector:"tb-enrichment-node-entity-details-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:er,decorators:[{type:n,args:[{selector:"tb-enrichment-node-entity-details-config",template:'
\n \n \n help\n \n \n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class tr extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[ke,Te,Le],this.aggregationTypes=w,this.aggregations=Object.values(w),this.aggregationTypesTranslations=G,this.fetchMode=_t,this.samplingOrders=Object.values(Ht),this.samplingOrdersTranslate=$t,this.timeUnits=Object.values(Gt),this.timeUnitsTranslationMap=Dt,this.deduplicationStrategiesHintTranslations=Kt,this.headerOptions=[],this.timeUnitMap={[Gt.MILLISECONDS]:1,[Gt.SECONDS]:1e3,[Gt.MINUTES]:6e4,[Gt.HOURS]:36e5,[Gt.DAYS]:864e5},this.intervalValidator=()=>e=>e.get("startInterval").value*this.timeUnitMap[e.get("startIntervalTimeUnit").value]<=e.get("endInterval").value*this.timeUnitMap[e.get("endIntervalTimeUnit").value]?{intervalError:!0}:null;for(const e of Bt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Bt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[_.required]],aggregation:[e.aggregation,[_.required]],fetchMode:[e.fetchMode,[_.required]],orderBy:[e.orderBy,[]],limit:[e.limit,[]],useMetadataIntervalPatterns:[e.useMetadataIntervalPatterns,[]],interval:this.fb.group({startInterval:[e.interval.startInterval,[]],startIntervalTimeUnit:[e.interval.startIntervalTimeUnit,[]],endInterval:[e.interval.endInterval,[]],endIntervalTimeUnit:[e.interval.endIntervalTimeUnit,[]]}),startIntervalPattern:[e.startIntervalPattern,[]],endIntervalPattern:[e.endIntervalPattern,[]]})}validatorTriggers(){return["fetchMode","useMetadataIntervalPatterns"]}toggleChange(e){this.getTelemetryFromDatabaseConfigForm.get("fetchMode").patchValue(e,{emitEvent:!0})}prepareOutputConfig(e){return e.startInterval=e.interval.startInterval,e.startIntervalTimeUnit=e.interval.startIntervalTimeUnit,e.endInterval=e.interval.endInterval,e.endIntervalTimeUnit=e.interval.endIntervalTimeUnit,delete e.interval,xe(e)}prepareInputConfig(e){return he(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:ye(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:ye(e?.aggregation)?e.aggregation:w.NONE,fetchMode:ye(e?.fetchMode)?e.fetchMode:_t.FIRST,orderBy:ye(e?.orderBy)?e.orderBy:Ht.ASC,limit:ye(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!ye(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:ye(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:ye(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:Gt.MINUTES,endInterval:ye(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:ye(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:Gt.MINUTES},startIntervalPattern:ye(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:ye(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===_t.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([_.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([_.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([_.required,_.min(2),_.max(1e3)])):(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([])),n?(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([_.required,_.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([_.required,_.min(1),_.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([_.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([_.required,_.min(1),_.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([_.required]),this.getTelemetryFromDatabaseConfigForm.get("interval").setValidators([this.intervalValidator()]),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").setValidators([]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([])),this.getTelemetryFromDatabaseConfigForm.get("aggregation").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("orderBy").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("limit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("interval").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").updateValueAndValidity({emitEvent:e}),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").updateValueAndValidity({emitEvent:e})}removeKey(e,t){const n=this.getTelemetryFromDatabaseConfigForm.get(t).value,r=n.indexOf(e);r>=0&&(n.splice(r,1),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(n,{emitEvent:!0}))}clearChipGrid(){this.getTelemetryFromDatabaseConfigForm.get("latestTsKeyNames").patchValue([],{emitEvent:!0})}addKey(e,t){const n=e.input;let r=e.value;if((r||"").trim()){r=r.trim();let e=this.getTelemetryFromDatabaseConfigForm.get(t).value;e&&-1!==e.indexOf(r)||(e||(e=[]),e.push(r),this.getTelemetryFromDatabaseConfigForm.get(t).setValue(e,{emitEvent:!0}))}n&&(n.value="")}defaultPaddingEnable(){return this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===_t.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===w.NONE}}e("GetTelemetryFromDatabaseConfigComponent",tr),tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:tr,selector:"tb-enrichment-node-get-telemetry-from-database",usesInheritance:!0,ngImport:t,template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:O.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:tr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-get-telemetry-from-database",template:'
\n \n
\n help\n \n
\n
\n
tb.rulenode.fetch-interval
\n
\n \n {{ \'tb.rulenode.use-metadata-dynamic-interval\' | translate }}\n \n
\n
\n
\n \n {{ \'tb.rulenode.interval-start\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n \n {{ \'tb.rulenode.interval-end\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-value-required\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n {{ \'tb.rulenode.time-value-range\' | translate }}\n \n \n \n {{ \'tb.rulenode.time-unit\' | translate }}\n \n \n {{ timeUnitsTranslationMap.get(timeUnit) | translate }}\n \n \n \n
\n
\n error_outline\n
\n \n {{ \'tb.rulenode.fetch-timeseries-from-to\' | translate:\n {\n startInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.startInterval\').value,\n endInterval: getTelemetryFromDatabaseConfigForm.get(\'interval.endInterval\').value,\n startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.startIntervalTimeUnit\').value.toLowerCase(),\n endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get(\'interval.endIntervalTimeUnit\').value.toLowerCase()\n } }}\n \n \n {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }}\n \n
\n
\n
\n \n
\n \n {{ \'tb.rulenode.start-interval\' | translate }}\n \n \n {{ \'tb.rulenode.start-interval-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.end-interval\' | translate }}\n \n \n {{ \'tb.rulenode.end-interval-required\' | translate }}\n \n \n \n \n
\n
\n
\n
\n
tb.rulenode.fetch-strategy
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get(\'fetchMode\').value) | translate }}\n
\n
\n
\n \n {{ \'aggregation.function\' | translate }}\n \n \n {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }}\n \n \n \n
\n \n {{ "tb.rulenode.order-by-timestamp" | translate }} \n \n \n {{ samplingOrdersTranslate.get(order) | translate }}\n \n \n \n \n {{ "tb.rulenode.limit" | translate }}\n \n {{ "tb.rulenode.limit-hint" | translate }}\n \n {{ \'tb.rulenode.limit-required\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n {{ \'tb.rulenode.limit-range\' | translate }}\n \n \n
\n
\n
\n
\n',styles:[":host .see-example{display:inline-block}:host .description-block{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}:host .description-block .description-icon{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}:host .description-block .description-text{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}:host .description-block.error{color:var(--mdc-theme-error, #f44336)}:host .description-block.error .description-icon{color:var(--mdc-theme-error, #f44336)}:host .item-center{align-items:center}:host .item-center .fetch-mod-toggle{width:100%}:host .hint-container{width:100%}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class nr extends g{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n}configForm(){return this.originatorAttributesConfigForm}onConfigurationSet(e){this.originatorAttributesConfigForm=this.fb.group({tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return he(e)&&(e.attributesControl={clientAttributeNames:ye(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:ye(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:ye(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:ye(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!ye(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA,tellFailureIfAbsent:!!ye(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:ye(e?.attributesControl)?e.attributesControl:null}}prepareOutputConfig(e){for(const t of Object.keys(e.attributesControl))e[t]=e.attributesControl[t];return delete e.attributesControl,e}}e("OriginatorAttributesConfigComponent",nr),nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,deps:[{token:R.Store},{token:X.TranslateService},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:nr,selector:"tb-enrichment-node-originator-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:$n,selector:"tb-select-attributes",inputs:["popupHelpLink"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:nr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-attributes-config",template:'
\n
\n
\n
tb.rulenode.originator-attributes
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n \n \n \n
\n
\n \n {{ \'tb.rulenode.tell-failure\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:X.TranslateService},{type:O.FormBuilder}]}});class rr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of At)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return xe(e)}prepareInputConfig(e){return{dataMapping:ye(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:ye(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[_.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}}e("OriginatorFieldsConfigComponent",rr),rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:rr,selector:"tb-enrichment-node-originator-fields-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n',dependencies:[{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Un,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:rr,decorators:[{type:n,args:[{selector:"tb-enrichment-node-originator-fields-config",template:'
\n \n \n \n \n
\n \n {{ \'tb.rulenode.skip-empty-fields\' | translate }}\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=zt,this.msgMetadataLabelTranslations=jt,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(At))this.originatorFields.push({value:At[e].value,name:this.translate.instant(At[e].name)});for(const e of Ut.keys())this.fetchToData.push({value:e,name:this.translate.instant(Ut.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===zt.FIELDS?(e.dataMapping=e.svMap,delete e.svMap):(e.dataMapping=e.kvMap,delete e.kvMap);const t={};if(e&&e.dataMapping)for(const n of Object.keys(e.dataMapping))t[n.trim()]=e.dataMapping[n];return e.dataMapping=t,delete e.svMap,delete e.kvMap,xe(e)}prepareInputConfig(e){let t,n,r={[k.name.value]:`relatedEntity${this.translate.instant(k.name.name)}`},o={serialNumber:"sn"};return t=ye(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:ye(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=ye(e?.attrMapping)?e.attrMapping:ye(e?.dataMapping)?e.dataMapping:null,t===zt.FIELDS?r=n:o=n,{relationsQuery:ye(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:o,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[_.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[_.required]],svMap:[e.svMap,[_.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===zt.FIELDS?(this.relatedAttributesConfigForm.get("svMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("svMap").updateValueAndValidity()):(this.relatedAttributesConfigForm.get("svMap").disable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").enable({emitEvent:!1}),this.relatedAttributesConfigForm.get("kvMap").updateValueAndValidity())}}e("RelatedAttributesConfigComponent",or),or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:or,selector:"tb-enrichment-node-related-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Rn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:_n,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"component",type:Un,selector:"tb-sv-map-config",inputs:["selectOptions","disabled","labelText","requiredText","targetKeyPrefix","selectText","selectRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:or,decorators:[{type:n,args:[{selector:"tb-enrichment-node-related-attributes-config",template:'
\n \n \n
\n
tb.rulenode.data-to-fetch
\n \n \n {{ data.name }}\n \n \n \n \n \n \n \n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class ar extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=zt;for(const e of Ut.keys())e!==zt.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(Ut.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=ye(e?.telemetry)?e.telemetry?zt.LATEST_TELEMETRY:zt.ATTRIBUTES:ye(e?.dataToFetch)?e.dataToFetch:zt.ATTRIBUTES,n=ye(e?.attrMapping)?e.attrMapping:ye(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===zt.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[_.required]],fetchTo:[e.fetchTo,[]]})}}e("TenantAttributesConfigComponent",ar),ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),ar.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ar,selector:"tb-enrichment-node-tenant-attributes-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:Z.DefaultLayoutAlignDirective,selector:" [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]",inputs:["fxLayoutAlign","fxLayoutAlign.xs","fxLayoutAlign.sm","fxLayoutAlign.md","fxLayoutAlign.lg","fxLayoutAlign.xl","fxLayoutAlign.lt-sm","fxLayoutAlign.lt-md","fxLayoutAlign.lt-lg","fxLayoutAlign.lt-xl","fxLayoutAlign.gt-xs","fxLayoutAlign.gt-sm","fxLayoutAlign.gt-md","fxLayoutAlign.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Rn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ar,decorators:[{type:n,args:[{selector:"tb-enrichment-node-tenant-attributes-config",template:'
\n
tb.rulenode.mapping-of-tenant
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class ir extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:ye(e?.fetchTo)?e.fetchTo:sn.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}}e("FetchDeviceCredentialsConfigComponent",ir),ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ir,selector:"./tb-enrichment-node-fetch-device-credentials-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ir,decorators:[{type:n,args:[{selector:"./tb-enrichment-node-fetch-device-credentials-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class lr{}e("RulenodeCoreConfigEnrichmentModule",lr),lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),lr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:lr,declarations:[Zn,er,Xn,nr,rr,tr,or,ar,Wn,ir],imports:[J,E,Qn],exports:[Zn,er,Xn,nr,rr,tr,or,ar,Wn,ir]}),lr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,imports:[J,E,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:lr,decorators:[{type:d,args:[{declarations:[Zn,er,Xn,nr,rr,tr,or,ar,Wn,ir],imports:[J,E,Qn],exports:[Zn,er,Xn,nr,rr,tr,or,ar,Wn,ir]}]}]});class sr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Zt,this.azureIotHubCredentialsTypeTranslationsMap=Xt}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[_.required]],host:[e?e.host:null,[_.required]],port:[e?e.port:null,[_.required,_.min(1),_.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[_.required,_.min(1),_.max(200)]],clientId:[e?e.clientId:null,[_.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[_.required]],sasKey:[e&&e.credentials?e.credentials.sasKey:null,[]],caCert:[e&&e.credentials?e.credentials.caCert:null,[]],caCertFileName:[e&&e.credentials?e.credentials.caCertFileName:null,[]],privateKey:[e&&e.credentials?e.credentials.privateKey:null,[]],privateKeyFileName:[e&&e.credentials?e.credentials.privateKeyFileName:null,[]],cert:[e&&e.credentials?e.credentials.cert:null,[]],certFileName:[e&&e.credentials?e.credentials.certFileName:null,[]],password:[e&&e.credentials?e.credentials.password:null,[]]})})}prepareOutputConfig(e){const t=e.credentials.type;return"sas"===t&&(e.credentials={type:t,sasKey:e.credentials.sasKey,caCert:e.credentials.caCert,caCertFileName:e.credentials.caCertFileName}),e}validatorTriggers(){return["credentials.type"]}updateValidators(e){const t=this.azureIotHubConfigForm.get("credentials"),n=t.get("type").value;switch(e&&t.reset({type:n},{emitEvent:!1}),t.get("sasKey").setValidators([]),t.get("privateKey").setValidators([]),t.get("privateKeyFileName").setValidators([]),t.get("cert").setValidators([]),t.get("certFileName").setValidators([]),n){case"sas":t.get("sasKey").setValidators([_.required]);break;case"cert.PEM":t.get("privateKey").setValidators([_.required]),t.get("privateKeyFileName").setValidators([_.required]),t.get("cert").setValidators([_.required]),t.get("certFileName").setValidators([_.required])}t.get("sasKey").updateValueAndValidity({emitEvent:e}),t.get("privateKey").updateValueAndValidity({emitEvent:e}),t.get("privateKeyFileName").updateValueAndValidity({emitEvent:e}),t.get("cert").updateValueAndValidity({emitEvent:e}),t.get("certFileName").updateValueAndValidity({emitEvent:e})}}e("AzureIotHubConfigComponent",sr),sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:sr,selector:"tb-external-node-azure-iot-hub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:j.NgSwitch,selector:"[ngSwitch]",inputs:["ngSwitch"]},{kind:"directive",type:j.NgSwitchCase,selector:"[ngSwitchCase]",inputs:["ngSwitchCase"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:ae.MatAccordion,selector:"mat-accordion",inputs:["multi","hideToggle","displayMode","togglePosition"],exportAs:["matAccordion"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:ae.MatExpansionPanelDescription,selector:"mat-panel-description"},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:O.FormGroupName,selector:"[formGroupName]",inputs:["formGroupName"]},{kind:"component",type:Xe.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:et.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:sr,decorators:[{type:n,args:[{selector:"tb-external-node-azure-iot-hub-config",template:'
\n \n tb.rulenode.topic\n \n \n {{ \'tb.rulenode.topic-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.hostname\n \n \n {{ \'tb.rulenode.hostname-required\' | translate }}\n \n \n \n tb.rulenode.device-id\n \n \n {{ \'tb.rulenode.device-id-required\' | translate }}\n \n \n \n \n \n tb.rulenode.credentials\n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get(\'credentials.type\').value) | translate }}\n \n \n
\n \n tb.rulenode.credentials-type\n \n \n {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }}\n \n \n \n {{ \'tb.rulenode.credentials-type-required\' | translate }}\n \n \n
\n \n \n \n \n tb.rulenode.sas-key\n \n \n \n {{ \'tb.rulenode.sas-key-required\' | translate }}\n \n \n \n \n \n \n \n \n \n \n \n \n \n tb.rulenode.private-key-password\n \n \n \n \n
\n
\n
\n
\n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class mr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=tn,this.ToByteStandartCharsetTypeTranslationMap=nn}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[_.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[_.required]],retries:[e?e.retries:null,[_.min(0)]],batchSize:[e?e.batchSize:null,[_.min(0)]],linger:[e?e.linger:null,[_.min(0)]],bufferMemory:[e?e.bufferMemory:null,[_.min(0)]],acks:[e?e.acks:null,[_.required]],keySerializer:[e?e.keySerializer:null,[_.required]],valueSerializer:[e?e.valueSerializer:null,[_.required]],otherProperties:[e?e.otherProperties:null,[]],addMetadataKeyValuesAsKafkaHeaders:[!!e&&e.addMetadataKeyValuesAsKafkaHeaders,[]],kafkaHeadersCharset:[e?e.kafkaHeadersCharset:null,[]]})}validatorTriggers(){return["addMetadataKeyValuesAsKafkaHeaders"]}updateValidators(e){this.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value?this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([_.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}}e("KafkaConfigComponent",mr),mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:mr,selector:"tb-external-node-kafka-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:mr,decorators:[{type:n,args:[{selector:"tb-external-node-kafka-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.key-pattern\n \n tb.rulenode.general-pattern-hint\n \n
tb.rulenode.key-pattern-hint
\n \n tb.rulenode.bootstrap-servers\n \n \n {{ \'tb.rulenode.bootstrap-servers-required\' | translate }}\n \n \n \n tb.rulenode.retries\n \n \n {{ \'tb.rulenode.min-retries-message\' | translate }}\n \n \n \n tb.rulenode.batch-size-bytes\n \n \n {{ \'tb.rulenode.min-batch-size-bytes-message\' | translate }}\n \n \n \n tb.rulenode.linger-ms\n \n \n {{ \'tb.rulenode.min-linger-ms-message\' | translate }}\n \n \n \n tb.rulenode.buffer-memory-bytes\n \n \n {{ \'tb.rulenode.min-buffer-memory-bytes-message\' | translate }}\n \n \n \n tb.rulenode.acks\n \n \n {{ ackValue }}\n \n \n \n \n tb.rulenode.key-serializer\n \n \n {{ \'tb.rulenode.key-serializer-required\' | translate }}\n \n \n \n tb.rulenode.value-serializer\n \n \n {{ \'tb.rulenode.value-serializer-required\' | translate }}\n \n \n \n \n \n \n {{ \'tb.rulenode.add-metadata-key-values-as-kafka-headers\' | translate }}\n \n
tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
\n \n tb.rulenode.charset-encoding\n \n \n {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class pr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.mqttConfigForm}onConfigurationSet(e){this.mqttConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[_.required]],host:[e?e.host:null,[_.required]],port:[e?e.port:null,[_.required,_.min(1),_.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[_.required,_.min(1),_.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&ve(e.clientId))},[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],cleanSession:[!!e&&e.cleanSession,[]],retainedMessage:[!!e&&e.retainedMessage,[]],ssl:[!!e&&e.ssl,[]],credentials:[e?e.credentials:null,[]]})}updateValidators(e){ve(this.mqttConfigForm.get("clientId").value)?this.mqttConfigForm.get("appendClientIdSuffix").enable({emitEvent:!1}):this.mqttConfigForm.get("appendClientIdSuffix").disable({emitEvent:!1}),this.mqttConfigForm.get("appendClientIdSuffix").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["clientId"]}}e("MqttConfigComponent",pr),pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),pr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:pr,selector:"tb-external-node-mqtt-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Kn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:pr,decorators:[{type:n,args:[{selector:"tb-external-node-mqtt-config",template:'
\n \n tb.rulenode.topic-pattern\n \n \n {{ \'tb.rulenode.topic-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n \n tb.rulenode.connect-timeout\n \n \n {{ \'tb.rulenode.connect-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n {{ \'tb.rulenode.connect-timeout-range\' | translate }}\n \n \n
\n \n tb.rulenode.client-id\n \n {{\'tb.rulenode.client-id-hint\' | translate}}\n \n \n {{ \'tb.rulenode.append-client-id-suffix\' | translate }}\n \n
{{ "tb.rulenode.client-id-suffix-hint" | translate }}
\n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
{{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
\n \n {{ \'tb.rulenode.clean-session\' | translate }}\n \n \n {{ "tb.rulenode.retained-message" | translate }}\n \n \n {{ \'tb.rulenode.enable-ssl\' | translate }}\n \n \n
\n',styles:[":host .tb-mqtt-credentials-panel-group{margin:0 6px}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class dr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=D,this.entityType=C}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[_.required]],targets:[e?e.targets:[],[_.required]]})}}e("NotificationConfigComponent",dr),dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),dr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:dr,selector:"tb-external-node-notification-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n
\n',dependencies:[{kind:"component",type:nt.EntityListComponent,selector:"tb-entity-list",inputs:["entityType","subType","labelText","placeholderText","requiredText","required","disabled","subscriptSizing","hint","syncIdsWithDB"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:rt.TemplateAutocompleteComponent,selector:"tb-template-autocomplete",inputs:["required","allowCreate","allowEdit","disabled","notificationTypes"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:dr,decorators:[{type:n,args:[{selector:"tb-external-node-notification-config",template:'
\n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.pubSubConfigForm}onConfigurationSet(e){this.pubSubConfigForm=this.fb.group({projectId:[e?e.projectId:null,[_.required]],topicName:[e?e.topicName:null,[_.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[_.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[_.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}}e("PubSubConfigComponent",ur),ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:ur,selector:"tb-external-node-pub-sub-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Xe.FileInputComponent,selector:"tb-file-input",inputs:["label","hint","accept","noFileText","inputId","allowedExtensions","dropLabel","maxSizeByte","contentConvertFunction","required","requiredAsError","disabled","existingFileName","readAsBinary","workFromFileObj","multipleFile"],outputs:["fileNameChanged"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:ur,decorators:[{type:n,args:[{selector:"tb-external-node-pub-sub-config",template:'
\n \n tb.rulenode.gcp-project-id\n \n \n {{ \'tb.rulenode.gcp-project-id-required\' | translate }}\n \n \n \n tb.rulenode.pubsub-topic-name\n \n \n {{ \'tb.rulenode.pubsub-topic-name-required\' | translate }}\n \n \n \n \n \n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class cr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"]}configForm(){return this.rabbitMqConfigForm}onConfigurationSet(e){this.rabbitMqConfigForm=this.fb.group({exchangeNamePattern:[e?e.exchangeNamePattern:null,[]],routingKeyPattern:[e?e.routingKeyPattern:null,[]],messageProperties:[e?e.messageProperties:null,[]],host:[e?e.host:null,[_.required]],port:[e?e.port:null,[_.required,_.min(1),_.max(65535)]],virtualHost:[e?e.virtualHost:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]],automaticRecoveryEnabled:[!!e&&e.automaticRecoveryEnabled,[]],connectionTimeout:[e?e.connectionTimeout:null,[_.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[_.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}}e("RabbitMqConfigComponent",cr),cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),cr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:cr,selector:"tb-external-node-rabbit-mq-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:et.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:cr,decorators:[{type:n,args:[{selector:"tb-external-node-rabbit-mq-config",template:'
\n \n tb.rulenode.exchange-name-pattern\n \n \n \n tb.rulenode.routing-key-pattern\n \n \n \n tb.rulenode.message-properties\n \n \n {{ property }}\n \n \n \n
\n \n tb.rulenode.host\n \n \n {{ \'tb.rulenode.host-required\' | translate }}\n \n \n \n tb.rulenode.port\n \n \n {{ \'tb.rulenode.port-required\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n {{ \'tb.rulenode.port-range\' | translate }}\n \n \n
\n \n tb.rulenode.virtual-host\n \n \n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n \n {{ \'tb.rulenode.automatic-recovery\' | translate }}\n \n \n tb.rulenode.connection-timeout-ms\n \n \n {{ \'tb.rulenode.min-connection-timeout-ms-message\' | translate }}\n \n \n \n tb.rulenode.handshake-timeout-ms\n \n \n {{ \'tb.rulenode.min-handshake-timeout-ms-message\' | translate }}\n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class gr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys(en)}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[_.required]],requestMethod:[e?e.requestMethod:null,[_.required]],useSimpleClientHttpFactory:[!!e&&e.useSimpleClientHttpFactory,[]],parseToPlainText:[!!e&&e.parseToPlainText,[]],ignoreRequestBody:[!!e&&e.ignoreRequestBody,[]],enableProxy:[!!e&&e.enableProxy,[]],useSystemProxyProperties:[!!e&&e.enableProxy,[]],proxyScheme:[e?e.proxyHost:null,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],readTimeoutMs:[e?e.readTimeoutMs:null,[]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[_.min(0)]],headers:[e?e.headers:null,[]],credentials:[e?e.credentials:null,[]],maxInMemoryBufferSizeInKb:[e?e.maxInMemoryBufferSizeInKb:null,[_.min(1)]]})}validatorTriggers(){return["useSimpleClientHttpFactory","enableProxy","useSystemProxyProperties"]}updateValidators(e){const t=this.restApiCallConfigForm.get("useSimpleClientHttpFactory").value,n=this.restApiCallConfigForm.get("enableProxy").value,r=this.restApiCallConfigForm.get("useSystemProxyProperties").value;n&&!r?(this.restApiCallConfigForm.get("proxyHost").setValidators(n?[_.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(n?[_.required,_.min(1),_.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([_.min(0)])),this.restApiCallConfigForm.get("readTimeoutMs").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e}),this.restApiCallConfigForm.get("credentials").updateValueAndValidity({emitEvent:e})}}e("RestApiCallConfigComponent",gr),gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),gr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:gr,selector:"tb-external-node-rest-api-call-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n tb.rulenode.max-response-size\n \n tb.rulenode.max-response-size-hint\n \n \n
\n \n \n \n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Kn,selector:"tb-credentials-config",inputs:["required","disableCertPemCredentials","passwordFieldRequired"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:gr,decorators:[{type:n,args:[{selector:"tb-external-node-rest-api-call-config",template:'
\n \n tb.rulenode.endpoint-url-pattern\n \n \n {{ \'tb.rulenode.endpoint-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.request-method\n \n \n {{ requestType }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n \n {{ \'tb.rulenode.use-simple-client-http-factory\' | translate }}\n \n \n {{ \'tb.rulenode.parse-to-plain-text\' | translate }}\n \n
tb.rulenode.parse-to-plain-text-hint
\n \n {{ \'tb.rulenode.ignore-request-body\' | translate }}\n \n
\n \n {{ \'tb.rulenode.use-system-proxy-properties\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-scheme\n \n \n {{ proxyScheme }}\n \n \n \n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n
\n \n tb.rulenode.read-timeout\n \n tb.rulenode.read-timeout-hint\n \n \n tb.rulenode.max-parallel-requests-count\n \n tb.rulenode.max-parallel-requests-count-hint\n \n \n tb.rulenode.max-response-size\n \n tb.rulenode.max-response-size-hint\n \n \n
\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.smtpProtocols=["smtp","smtps"],this.tlsVersions=["TLSv1","TLSv1.1","TLSv1.2","TLSv1.3"]}configForm(){return this.sendEmailConfigForm}onConfigurationSet(e){this.sendEmailConfigForm=this.fb.group({useSystemSmtpSettings:[!!e&&e.useSystemSmtpSettings,[]],smtpProtocol:[e?e.smtpProtocol:null,[]],smtpHost:[e?e.smtpHost:null,[]],smtpPort:[e?e.smtpPort:null,[]],timeout:[e?e.timeout:null,[]],enableTls:[!!e&&e.enableTls,[]],tlsVersion:[e?e.tlsVersion:null,[]],enableProxy:[!!e&&e.enableProxy,[]],proxyHost:[e?e.proxyHost:null,[]],proxyPort:[e?e.proxyPort:null,[]],proxyUser:[e?e.proxyUser:null,[]],proxyPassword:[e?e.proxyPassword:null,[]],username:[e?e.username:null,[]],password:[e?e.password:null,[]]})}validatorTriggers(){return["useSystemSmtpSettings","enableProxy"]}updateValidators(e){const t=this.sendEmailConfigForm.get("useSystemSmtpSettings").value,n=this.sendEmailConfigForm.get("enableProxy").value;t?(this.sendEmailConfigForm.get("smtpProtocol").setValidators([]),this.sendEmailConfigForm.get("smtpHost").setValidators([]),this.sendEmailConfigForm.get("smtpPort").setValidators([]),this.sendEmailConfigForm.get("timeout").setValidators([]),this.sendEmailConfigForm.get("proxyHost").setValidators([]),this.sendEmailConfigForm.get("proxyPort").setValidators([])):(this.sendEmailConfigForm.get("smtpProtocol").setValidators([_.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([_.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([_.required,_.min(1),_.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([_.required,_.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[_.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[_.required,_.min(1),_.max(65535)]:[])),this.sendEmailConfigForm.get("smtpProtocol").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("smtpPort").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("timeout").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyHost").updateValueAndValidity({emitEvent:e}),this.sendEmailConfigForm.get("proxyPort").updateValueAndValidity({emitEvent:e})}}e("SendEmailConfigComponent",fr),fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:fr,selector:"tb-external-node-send-email-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ot.TbCheckboxComponent,selector:"tb-checkbox",inputs:["disabled","trueValue","falseValue"],outputs:["valueChange"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:et.TogglePasswordComponent,selector:"tb-toggle-password"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:fr,decorators:[{type:n,args:[{selector:"tb-external-node-send-email-config",template:'
\n \n {{ \'tb.rulenode.use-system-smtp-settings\' | translate }}\n \n
\n \n tb.rulenode.smtp-protocol\n \n \n {{ smtpProtocol.toUpperCase() }}\n \n \n \n
\n \n tb.rulenode.smtp-host\n \n \n {{ \'tb.rulenode.smtp-host-required\' | translate }}\n \n \n \n tb.rulenode.smtp-port\n \n \n {{ \'tb.rulenode.smtp-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n {{ \'tb.rulenode.smtp-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.timeout-msec\n \n \n {{ \'tb.rulenode.timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.min-timeout-msec-message\' | translate }}\n \n \n \n {{ \'tb.rulenode.enable-tls\' | translate }}\n \n \n tb.rulenode.tls-version\n \n \n {{ tlsVersion }}\n \n \n \n \n {{ \'tb.rulenode.enable-proxy\' | translate }}\n \n
\n
\n \n tb.rulenode.proxy-host\n \n \n {{ \'tb.rulenode.proxy-host-required\' | translate }}\n \n \n \n tb.rulenode.proxy-port\n \n \n {{ \'tb.rulenode.proxy-port-required\' | translate }}\n \n \n {{ \'tb.rulenode.proxy-port-range\' | translate }}\n \n \n
\n \n tb.rulenode.proxy-user\n \n \n \n tb.rulenode.proxy-password\n \n \n
\n \n tb.rulenode.username\n \n \n \n tb.rulenode.password\n \n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class yr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.sendSmsConfigForm}onConfigurationSet(e){this.sendSmsConfigForm=this.fb.group({numbersToTemplate:[e?e.numbersToTemplate:null,[_.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[_.required]],useSystemSmsSettings:[!!e&&e.useSystemSmsSettings,[]],smsProviderConfiguration:[e?e.smsProviderConfiguration:null,[]]})}validatorTriggers(){return["useSystemSmsSettings"]}updateValidators(e){this.sendSmsConfigForm.get("useSystemSmsSettings").value?this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([]):this.sendSmsConfigForm.get("smsProviderConfiguration").setValidators([_.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}}e("SendSmsConfigComponent",yr),yr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),yr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:yr,selector:"tb-external-node-send-sms-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:at.SmsProviderConfigurationComponent,selector:"tb-sms-provider-configuration",inputs:["required","disabled"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:yr,decorators:[{type:n,args:[{selector:"tb-external-node-send-sms-config",template:'
\n \n tb.rulenode.numbers-to-template\n \n \n {{ \'tb.rulenode.numbers-to-template-required\' | translate }}\n \n \n \n \n tb.rulenode.sms-message-template\n \n \n {{ \'tb.rulenode.sms-message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-sms-settings\' | translate }}\n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class br extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(V),this.slackChanelTypesTranslateMap=P}configForm(){return this.slackConfigForm}onConfigurationSet(e){this.slackConfigForm=this.fb.group({botToken:[e?e.botToken:null],useSystemSettings:[!!e&&e.useSystemSettings],messageTemplate:[e?e.messageTemplate:null,[_.required]],conversationType:[e?e.conversationType:null,[_.required]],conversation:[e?e.conversation:null,[_.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([_.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}}e("SlackConfigComponent",br),br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:br,selector:"tb-external-node-slack-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ie.MatCheckbox,selector:"mat-checkbox",inputs:["disableRipple","color","tabIndex"],exportAs:["matCheckbox"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:it.MatRadioGroup,selector:"mat-radio-group",exportAs:["matRadioGroup"]},{kind:"component",type:it.MatRadioButton,selector:"mat-radio-button",inputs:["disableRipple","tabIndex"],exportAs:["matRadioButton"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:lt.SlackConversationAutocompleteComponent,selector:"tb-slack-conversation-autocomplete",inputs:["labelText","requiredText","required","disabled","slackChanelType","token"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:br,decorators:[{type:n,args:[{selector:"tb-external-node-slack-config",template:'
\n \n tb.rulenode.message-template\n \n \n {{ \'tb.rulenode.message-template-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n {{ \'tb.rulenode.use-system-slack-settings\' | translate }}\n \n \n tb.rulenode.slack-api-token\n \n \n {{ \'tb.rulenode.slack-api-token-required\' | translate }}\n \n \n \n \n \n {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }}\n \n \n \n \n
\n',styles:[":host .tb-title{display:block;padding-bottom:6px}:host ::ng-deep .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}:host ::ng-deep .mat-mdc-radio-group .mat-mdc-radio-button{flex:1 1 100%;padding:4px;border:1px solid rgba(0,0,0,.12);border-radius:6px}@media screen and (max-width: 599px){:host ::ng-deep .mat-mdc-radio-group{flex-direction:column}}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class xr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.snsConfigForm}onConfigurationSet(e){this.snsConfigForm=this.fb.group({topicArnPattern:[e?e.topicArnPattern:null,[_.required]],accessKeyId:[e?e.accessKeyId:null,[_.required]],secretAccessKey:[e?e.secretAccessKey:null,[_.required]],region:[e?e.region:null,[_.required]]})}}e("SnsConfigComponent",xr),xr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),xr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:xr,selector:"tb-external-node-sns-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:xr,decorators:[{type:n,args:[{selector:"tb-external-node-sns-config",template:'
\n \n tb.rulenode.topic-arn-pattern\n \n \n {{ \'tb.rulenode.topic-arn-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Jt,this.sqsQueueTypes=Object.keys(Jt),this.sqsQueueTypeTranslationsMap=Qt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[_.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[_.required]],delaySeconds:[e?e.delaySeconds:null,[_.min(0),_.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[_.required]],secretAccessKey:[e?e.secretAccessKey:null,[_.required]],region:[e?e.region:null,[_.required]]})}}e("SqsConfigComponent",hr),hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:hr,selector:"tb-external-node-sqs-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Nn,selector:"tb-kv-map-config-old",inputs:["disabled","uniqueKeyValuePairValidator","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","required"]},{kind:"pipe",type:ce.SafePipe,name:"safe"},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:hr,decorators:[{type:n,args:[{selector:"tb-external-node-sqs-config",template:'
\n \n tb.rulenode.queue-type\n \n \n {{ sqsQueueTypeTranslationsMap.get(type) | translate }}\n \n \n \n \n tb.rulenode.queue-url-pattern\n \n \n {{ \'tb.rulenode.queue-url-pattern-required\' | translate }}\n \n tb.rulenode.general-pattern-hint\n \n \n tb.rulenode.delay-seconds\n \n \n {{ \'tb.rulenode.min-delay-seconds-message\' | translate }}\n \n \n {{ \'tb.rulenode.max-delay-seconds-message\' | translate }}\n \n \n \n
\n \n \n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class vr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.lambdaConfigForm}onConfigurationSet(e){this.lambdaConfigForm=this.fb.group({functionName:[e?e.functionName:null,[_.required]],qualifier:[e?e.qualifier:null,[]],accessKey:[e?e.accessKey:null,[_.required]],secretKey:[e?e.secretKey:null,[_.required]],region:[e?e.region:null,[_.required]],connectionTimeout:[e?e.connectionTimeout:null,[_.required,_.min(0)]],requestTimeout:[e?e.requestTimeout:null,[_.required,_.min(0)]],tellFailureIfFuncThrowsExc:[!!e&&e.tellFailureIfFuncThrowsExc,[]]})}}e("LambdaConfigComponent",vr),vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),vr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:vr,selector:"tb-external-node-lambda-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n
tb.rulenode.function-configuration
\n
\n \n \n
\n \n {{\'tb.rulenode.function-name\' | translate}}\n \n \n {{\'tb.rulenode.function-name-required\' | translate}}\n \n \n \n {{\'tb.rulenode.qualifier\' | translate}}\n \n tb.rulenode.qualifier-hint\n \n
\n
\n\n
\n \n \n tb.rulenode.aws-credentials\n \n
\n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n tb.rulenode.connection-timeout\n \n \n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n \n help\n \n \n tb.rulenode.request-timeout\n \n \n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n \n help\n \n
\n
\n \n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:vr,decorators:[{type:n,args:[{selector:"tb-external-node-lambda-config",template:'
\n
\n
\n
tb.rulenode.function-configuration
\n
\n \n \n
\n \n {{\'tb.rulenode.function-name\' | translate}}\n \n \n {{\'tb.rulenode.function-name-required\' | translate}}\n \n \n \n {{\'tb.rulenode.qualifier\' | translate}}\n \n tb.rulenode.qualifier-hint\n \n
\n
\n\n
\n \n \n tb.rulenode.aws-credentials\n \n
\n \n tb.rulenode.aws-access-key-id\n \n \n {{ \'tb.rulenode.aws-access-key-id-required\' | translate }}\n \n \n \n tb.rulenode.aws-secret-access-key\n \n \n {{ \'tb.rulenode.aws-secret-access-key-required\' | translate }}\n \n \n \n tb.rulenode.aws-region\n \n \n {{ \'tb.rulenode.aws-region-required\' | translate }}\n \n \n
\n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n
\n \n tb.rulenode.connection-timeout\n \n \n {{ \'tb.rulenode.connection-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.connection-timeout-min\' | translate }}\n \n help\n \n \n tb.rulenode.request-timeout\n \n \n {{ \'tb.rulenode.request-timeout-required\' | translate }}\n \n \n {{ \'tb.rulenode.request-timeout-min\' | translate }}\n \n help\n \n
\n
\n \n {{ \'tb.rulenode.tell-failure-aws-lambda\' | translate }}\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Cr{}e("RulenodeCoreConfigExternalModule",Cr),Cr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Cr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Cr,declarations:[xr,hr,vr,ur,mr,pr,dr,cr,gr,fr,sr,yr,br],imports:[J,E,Qe,Qn],exports:[xr,hr,vr,ur,mr,pr,dr,cr,gr,fr,sr,yr,br]}),Cr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,imports:[J,E,Qe,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Cr,decorators:[{type:d,args:[{declarations:[xr,hr,vr,ur,mr,pr,dr,cr,gr,fr,sr,yr,br],imports:[J,E,Qe,Qn],exports:[xr,hr,vr,ur,mr,pr,dr,cr,gr,fr,sr,yr,br]}]}]});class Fr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:ye(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[_.required]]})}}e("CheckAlarmStatusComponent",Fr),Fr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Fr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Fr,selector:"tb-filter-node-check-alarm-status-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:Jn,selector:"tb-alarm-status-select"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Fr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-alarm-status-config",template:'
\n
\n
tb.rulenode.alarm-status
\n
\n tb.rulenode.alarm-required\n
\n
\n \n
\n\n\n\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class kr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:ye(e?.messageNames)?e.messageNames:[],metadataNames:ye(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!ye(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:ye(e?.messageNames)?e.messageNames:[],metadataNames:ye(e?.metadataNames)?e.metadataNames:[],checkAllKeys:e.checkAllKeys}}atLeastOne(e,t=null){return n=>{t||(t=Object.keys(n.controls));return n?.controls&&t.some((t=>!e(n.controls[t])))?null:{atLeastOne:!0}}}onConfigurationSet(e){this.checkMessageConfigForm=this.fb.group({messageNames:[e.messageNames,[]],metadataNames:[e.metadataNames,[]],checkAllKeys:[e.checkAllKeys,[]]},{validators:this.atLeastOne(_.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}}e("CheckMessageConfigComponent",kr),kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:kr,selector:"tb-filter-node-check-message-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:kr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-message-config",template:'
\n
\n
tb.rulenode.fields-to-check
\n
\n tb.rulenode.at-least-one-field-required\n
\n
\n \n help\n \n \n help\n \n
\n \n {{ \'tb.rulenode.check-all-keys\' | translate }}\n \n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Tr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(v),this.entitySearchDirectionTranslationsMap=N}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!ye(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:ye(e?.direction)?e.direction:null,entityType:ye(e?.entityType)?e.entityType:null,entityId:ye(e?.entityId)?e.entityId:null,relationType:ye(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[_.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[_.required]:[]],relationType:[e.relationType,[_.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[_.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[_.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}}e("CheckRelationConfigComponent",Tr),Tr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Tr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Tr,selector:"tb-filter-node-check-relation-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:st.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled","additionEntityTypes"]},{kind:"component",type:qe.RelationTypeAutocompleteComponent,selector:"tb-relation-type-autocomplete",inputs:["showLabel","additionalClasses","appearance","required","disabled","subscriptSizing"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Tr,decorators:[{type:n,args:[{selector:"tb-filter-node-check-relation-config",template:'
\n
tb.rulenode.relation-search-parameters
\n
\n \n {{ \'relation.direction\' | translate }}\n \n \n {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix\n \n \n \n \n \n
\n \n {{ \'tb.rulenode.check-relation-to-specific-entity\' | translate }}\n \n
\n
\n \n \n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Lr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=Et,this.perimeterTypes=Object.values(Et),this.perimeterTypeTranslationMap=wt,this.rangeUnits=Object.values(Vt),this.rangeUnitTranslationMap=Pt,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:ye(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:ye(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:ye(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!ye(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:ye(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:ye(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:ye(e?.centerLongitude)?e.centerLongitude:null,range:ye(e?.range)?e.range:null,rangeUnit:ye(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:ye(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[_.required]],longitudeKeyName:[e.longitudeKeyName,[_.required]],perimeterType:[e.perimeterType,[_.required]],fetchPerimeterInfoFromMessageMetadata:[e.fetchPerimeterInfoFromMessageMetadata,[]],perimeterKeyName:[e.perimeterKeyName,[]],centerLatitude:[e.centerLatitude,[]],centerLongitude:[e.centerLongitude,[]],range:[e.range,[]],rangeUnit:[e.rangeUnit,[]],polygonsDefinition:[e.polygonsDefinition,[]]})}validatorTriggers(){return["fetchPerimeterInfoFromMessageMetadata","perimeterType"]}updateValidators(e){const t=this.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value,n=this.geoFilterConfigForm.get("perimeterType").value;t?this.geoFilterConfigForm.get("perimeterKeyName").setValidators([_.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==Et.CIRCLE?(this.geoFilterConfigForm.get("centerLatitude").setValidators([]),this.geoFilterConfigForm.get("centerLongitude").setValidators([]),this.geoFilterConfigForm.get("range").setValidators([]),this.geoFilterConfigForm.get("rangeUnit").setValidators([]),this.defaultPaddingEnable=!0):(this.geoFilterConfigForm.get("centerLatitude").setValidators([_.required,_.min(-90),_.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([_.required,_.min(-180),_.max(180)]),this.geoFilterConfigForm.get("range").setValidators([_.required,_.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([_.required]),this.defaultPaddingEnable=!1),t||n!==Et.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([_.required]),this.geoFilterConfigForm.get("perimeterKeyName").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLatitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("centerLongitude").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("range").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("rangeUnit").updateValueAndValidity({emitEvent:e}),this.geoFilterConfigForm.get("polygonsDefinition").updateValueAndValidity({emitEvent:e})}}e("GpsGeoFilterConfigComponent",Lr),Lr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Lr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Lr,selector:"tb-filter-node-gps-geofencing-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:Z.DefaultLayoutGapDirective,selector:" [fxLayoutGap], [fxLayoutGap.xs], [fxLayoutGap.sm], [fxLayoutGap.md], [fxLayoutGap.lg], [fxLayoutGap.xl], [fxLayoutGap.lt-sm], [fxLayoutGap.lt-md], [fxLayoutGap.lt-lg], [fxLayoutGap.lt-xl], [fxLayoutGap.gt-xs], [fxLayoutGap.gt-sm], [fxLayoutGap.gt-md], [fxLayoutGap.gt-lg]",inputs:["fxLayoutGap","fxLayoutGap.xs","fxLayoutGap.sm","fxLayoutGap.md","fxLayoutGap.lg","fxLayoutGap.xl","fxLayoutGap.lt-sm","fxLayoutGap.lt-md","fxLayoutGap.lt-lg","fxLayoutGap.lt-xl","fxLayoutGap.gt-xs","fxLayoutGap.gt-sm","fxLayoutGap.gt-md","fxLayoutGap.gt-lg"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.MinValidator,selector:"input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]",inputs:["min"]},{kind:"directive",type:O.MaxValidator,selector:"input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]",inputs:["max"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Lr,decorators:[{type:n,args:[{selector:"tb-filter-node-gps-geofencing-config",template:'
\n
\n
tb.rulenode.coordinate-field-names
\n
\n
\n \n {{ \'tb.rulenode.latitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.latitude-field-name-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.longitude-field-name\' | translate }}\n \n \n {{ \'tb.rulenode.longitude-field-name-required\' | translate }}\n \n \n
\n
tb.rulenode.coordinate-field-hint
\n
\n
\n
\n
tb.rulenode.geofence-configuration
\n
\n \n {{ \'tb.rulenode.perimeter-type\' | translate }}\n \n \n {{ perimeterTypeTranslationMap.get(type) | translate }}\n \n \n \n
\n \n {{ \'tb.rulenode.fetch-perimeter-info-from-metadata\' | translate }}\n \n
\n \n {{ \'tb.rulenode.perimeter-key-name\' | translate }}\n \n \n {{ \'tb.rulenode.perimeter-key-name-required\' | translate }}\n \n {{ \'tb.rulenode.perimeter-key-name-hint\' | translate }}\n \n
\n
\n \n {{ \'tb.rulenode.circle-center-latitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-latitude-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.circle-center-longitude\' | translate }}\n \n \n {{ \'tb.rulenode.circle-center-longitude-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.range\' | translate }}\n \n \n {{ \'tb.rulenode.range-required\' | translate }}\n \n \n \n {{ \'tb.rulenode.range-units\' | translate }}\n \n \n {{ rangeUnitTranslationMap.get(type) | translate }}\n \n \n \n {{ \'tb.rulenode.range-units-required\' | translate }}\n \n \n
\n
\n \n {{ \'tb.rulenode.polygon-definition\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-hint\' | translate }}\n \n {{ \'tb.rulenode.polygon-definition-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .slide-toggle{margin-bottom:18px}\n",':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Ir extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:ye(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[_.required]]})}}e("MessageTypeConfigComponent",Ir),Ir.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ir.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ir,selector:"tb-filter-node-message-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n
\n',dependencies:[{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Bn,selector:"tb-message-types-config",inputs:["required","label","placeholder","disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ir,decorators:[{type:n,args:[{selector:"tb-filter-node-message-type-config",template:'
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Sr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.TENANT,C.CUSTOMER,C.USER,C.DASHBOARD,C.RULE_CHAIN,C.RULE_NODE,C.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:ye(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[_.required]]})}}e("OriginatorTypeConfigComponent",Sr),Sr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Sr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Sr,selector:"tb-filter-node-originator-type-config",usesInheritance:!0,ngImport:t,template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:mt.EntityTypeListComponent,selector:"tb-entity-type-list",inputs:["required","additionalClasses","appearance","label","floatLabel","disabled","subscriptSizing","allowedEntityTypes","emptyInputPlaceholder","filledInputPlaceholder","ignoreAuthorityFilter"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:Z.DefaultFlexDirective,selector:" [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]",inputs:["fxFlex","fxFlex.xs","fxFlex.sm","fxFlex.md","fxFlex.lg","fxFlex.xl","fxFlex.lt-sm","fxFlex.lt-md","fxFlex.lt-lg","fxFlex.lt-xl","fxFlex.gt-xs","fxFlex.gt-sm","fxFlex.gt-md","fxFlex.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Sr,decorators:[{type:n,args:[{selector:"tb-filter-node-originator-type-config",template:'
\n \n help\n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class Nr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[_.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:ye(e?.scriptLang)?e.scriptLang:b.JS,jsScript:ye(e?.jsScript)?e.jsScript:null,tbelScript:ye(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"filter",this.translate.instant("tb.rulenode.filter"),"Filter",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("ScriptConfigComponent",Nr),Nr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Nr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Nr,selector:"tb-filter-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Nr,decorators:[{type:n,args:[{selector:"tb-filter-node-script-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class qr extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[_.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),{scriptLang:ye(e?.scriptLang)?e.scriptLang:b.JS,jsScript:ye(e?.jsScript)?e.jsScript:null,tbelScript:ye(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",o=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"switch",this.translate.instant("tb.rulenode.switch"),"Switch",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.switchConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.switchConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("SwitchConfigComponent",qr),qr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,deps:[{token:R.Store},{token:O.UntypedFormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),qr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:qr,selector:"tb-filter-node-switch-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n \n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:qr,decorators:[{type:n,args:[{selector:"tb-filter-node-switch-config",template:'
\n \n \n \n \n \n \n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}});class Ar{}e("RuleNodeCoreConfigFilterModule",Ar),Ar.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Ar.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Ar,declarations:[kr,Tr,Lr,Ir,Sr,Nr,qr,Fr],imports:[J,E,Qn],exports:[kr,Tr,Lr,Ir,Sr,Nr,qr,Fr]}),Ar.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,imports:[J,E,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ar,decorators:[{type:d,args:[{declarations:[kr,Tr,Lr,Ir,Sr,Nr,qr,Fr],imports:[J,E,Qn],exports:[kr,Tr,Lr,Ir,Sr,Nr,qr,Fr]}]}]});class Mr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=St,this.originatorSources=Object.keys(St),this.originatorSourceTranslationMap=Nt,this.originatorSourceDescTranslationMap=qt,this.allowedEntityTypes=[C.DEVICE,C.ASSET,C.ENTITY_VIEW,C.USER,C.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[_.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationsQuery:[e?e.relationsQuery:null,[]]})}validatorTriggers(){return["originatorSource"]}updateValidators(e){const t=this.changeOriginatorConfigForm.get("originatorSource").value;t===St.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([_.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===St.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([_.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([_.required,_.pattern(/.*\S.*/)])):(this.changeOriginatorConfigForm.get("entityType").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").patchValue(null,{emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").setValidators([]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([])),this.changeOriginatorConfigForm.get("relationsQuery").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.changeOriginatorConfigForm.get("entityNamePattern").updateValueAndValidity({emitEvent:e})}}e("ChangeOriginatorConfigComponent",Mr),Mr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Mr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Mr,selector:"tb-transformation-node-change-originator-config",usesInheritance:!0,ngImport:t,template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n',dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ne.EntityTypeSelectComponent,selector:"tb-entity-type-select",inputs:["allowedEntityTypes","useAliasEntityTypes","filterAllowedEntityTypes","showLabel","required","disabled","additionEntityTypes"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:ne.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Re.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Re.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:_n,selector:"tb-relations-query-config",inputs:["disabled","required"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Mr,decorators:[{type:n,args:[{selector:"tb-transformation-node-change-originator-config",template:'
\n \n tb.rulenode.new-originator\n \n \n \n {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get(\'originatorSource\').value) | translate }}\n \n \n \n \n {{ originatorSourceTranslationMap.get(source) | translate }}\n \n
\n \n {{ originatorSourceDescTranslationMap.get(source) | translate }}\n \n
\n
\n
\n
\n \n \n
\n \n \n \n tb.rulenode.entity-name-pattern\n \n \n {{ \'tb.rulenode.entity-name-pattern-required\' | translate }}\n \n \n
\n
\n \n \n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Er extends g{constructor(e,t,n,r){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=n,this.translate=r,this.tbelEnabled=ge(this.store).tbelEnabled,this.scriptLanguage=b,this.changeScript=new l,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-transformer-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e?e.scriptLang:b.JS,[_.required]],jsScript:[e?e.jsScript:null,[_.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==b.TBEL||this.tbelEnabled||(t=b.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===b.JS?[_.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===b.TBEL?[_.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=b.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===b.JS?"jsScript":"tbelScript",r=t===b.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",o=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(o,"update",this.translate.instant("tb.rulenode.transformer"),"Transform",["msg","metadata","msgType"],this.ruleNodeId,r,t,e).subscribe((e=>{e&&(this.scriptConfigForm.get(n).setValue(e),this.changeScript.emit())}))}onValidate(){this.scriptConfigForm.get("scriptLang").value===b.JS&&this.jsFuncComponent.validateOnSubmit()}}e("TransformScriptConfigComponent",Er),Er.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,deps:[{token:R.Store},{token:O.FormBuilder},{token:fe.NodeScriptTestService},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Er.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Er,selector:"tb-transformation-node-script-config",viewQueries:[{propertyName:"jsFuncComponent",first:!0,predicate:["jsFuncComponent"],descendants:!0},{propertyName:"tbelFuncComponent",first:!0,predicate:["tbelFuncComponent"],descendants:!0}],usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n',dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:Ce.JsFuncComponent,selector:"tb-js-func",inputs:["functionTitle","functionName","functionArgs","validationArgs","resultType","disabled","fillHeight","minHeight","editorCompleter","propertyHighlightRules","objectHighlightRules","globalVariables","disableUndefinedCheck","helpId","scriptLanguage","hideBrackets","noValidate","required"]},{kind:"component",type:ee.MatButton,selector:" button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:ee.MatIconButton,selector:"button[mat-icon-button]",inputs:["disabled","disableRipple","color"],exportAs:["matButton"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:Fe.TbScriptLangComponent,selector:"tb-script-lang",inputs:["disabled"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Er,decorators:[{type:n,args:[{selector:"tb-transformation-node-script-config",template:'
\n \n \n \n \n \n \n \n
\n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:fe.NodeScriptTestService},{type:X.TranslateService}]},propDecorators:{jsFuncComponent:[{type:u,args:["jsFuncComponent",{static:!1}]}],tbelFuncComponent:[{type:u,args:["tbelFuncComponent",{static:!1}]}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + const wr=pt({passive:!0});class Gr{constructor(e,t){this._platform=e,this._ngZone=t,this._monitoredElements=new Map}monitor(e){if(!this._platform.isBrowser)return me;const t=Ge(e),n=this._monitoredElements.get(t);if(n)return n.subject;const r=new ie,o="cdk-text-field-autofilled",a=e=>{"cdk-text-field-autofill-start"!==e.animationName||t.classList.contains(o)?"cdk-text-field-autofill-end"===e.animationName&&t.classList.contains(o)&&(t.classList.remove(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!1})))):(t.classList.add(o),this._ngZone.run((()=>r.next({target:e.target,isAutofilled:!0}))))};return this._ngZone.runOutsideAngular((()=>{t.addEventListener("animationstart",a,wr),t.classList.add("cdk-text-field-autofill-monitored")})),this._monitoredElements.set(t,{subject:r,unlisten:()=>{t.removeEventListener("animationstart",a,wr)}}),r}stopMonitoring(e){const t=Ge(e),n=this._monitoredElements.get(t);n&&(n.unlisten(),n.subject.complete(),t.classList.remove("cdk-text-field-autofill-monitored"),t.classList.remove("cdk-text-field-autofilled"),this._monitoredElements.delete(t))}ngOnDestroy(){this._monitoredElements.forEach(((e,t)=>this.stopMonitoring(t)))}}Gr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,deps:[{token:dt.Platform},{token:t.NgZone}],target:t.ɵɵFactoryTarget.Injectable}),Gr.ɵprov=t.ɵɵngDeclareInjectable({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,providedIn:"root"}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Gr,decorators:[{type:o,args:[{providedIn:"root"}]}],ctorParameters:function(){return[{type:dt.Platform},{type:t.NgZone}]}});class Dr{constructor(e,t){this._elementRef=e,this._autofillMonitor=t,this.cdkAutofill=new l}ngOnInit(){this._autofillMonitor.monitor(this._elementRef).subscribe((e=>this.cdkAutofill.emit(e)))}ngOnDestroy(){this._autofillMonitor.stopMonitoring(this._elementRef)}}Dr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,deps:[{token:t.ElementRef},{token:Gr}],target:t.ɵɵFactoryTarget.Directive}),Dr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Dr,selector:"[cdkAutofill]",outputs:{cdkAutofill:"cdkAutofill"},ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Dr,decorators:[{type:s,args:[{selector:"[cdkAutofill]"}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:Gr}]},propDecorators:{cdkAutofill:[{type:p}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Vr{get minRows(){return this._minRows}set minRows(e){this._minRows=De(e),this._setMinHeight()}get maxRows(){return this._maxRows}set maxRows(e){this._maxRows=De(e),this._setMaxHeight()}get enabled(){return this._enabled}set enabled(e){e=we(e),this._enabled!==e&&((this._enabled=e)?this.resizeToFitContent(!0):this.reset())}get placeholder(){return this._textareaElement.placeholder}set placeholder(e){this._cachedPlaceholderHeight=void 0,e?this._textareaElement.setAttribute("placeholder",e):this._textareaElement.removeAttribute("placeholder"),this._cacheTextareaPlaceholderHeight()}constructor(e,t,n,r){this._elementRef=e,this._platform=t,this._ngZone=n,this._destroyed=new ie,this._enabled=!0,this._previousMinRows=-1,this._isViewInited=!1,this._handleFocusEvent=e=>{this._hasFocus="focus"===e.type},this._document=r,this._textareaElement=this._elementRef.nativeElement}_setMinHeight(){const e=this.minRows&&this._cachedLineHeight?this.minRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.minHeight=e)}_setMaxHeight(){const e=this.maxRows&&this._cachedLineHeight?this.maxRows*this._cachedLineHeight+"px":null;e&&(this._textareaElement.style.maxHeight=e)}ngAfterViewInit(){this._platform.isBrowser&&(this._initialHeight=this._textareaElement.style.height,this.resizeToFitContent(),this._ngZone.runOutsideAngular((()=>{const e=this._getWindow();pe(e,"resize").pipe(je(16),Ue(this._destroyed)).subscribe((()=>this.resizeToFitContent(!0))),this._textareaElement.addEventListener("focus",this._handleFocusEvent),this._textareaElement.addEventListener("blur",this._handleFocusEvent)})),this._isViewInited=!0,this.resizeToFitContent(!0))}ngOnDestroy(){this._textareaElement.removeEventListener("focus",this._handleFocusEvent),this._textareaElement.removeEventListener("blur",this._handleFocusEvent),this._destroyed.next(),this._destroyed.complete()}_cacheTextareaLineHeight(){if(this._cachedLineHeight)return;let e=this._textareaElement.cloneNode(!1);e.rows=1,e.style.position="absolute",e.style.visibility="hidden",e.style.border="none",e.style.padding="0",e.style.height="",e.style.minHeight="",e.style.maxHeight="",e.style.overflow="hidden",this._textareaElement.parentNode.appendChild(e),this._cachedLineHeight=e.clientHeight,e.remove(),this._setMinHeight(),this._setMaxHeight()}_measureScrollHeight(){const e=this._textareaElement,t=e.style.marginBottom||"",n=this._platform.FIREFOX,r=n&&this._hasFocus,o=n?"cdk-textarea-autosize-measuring-firefox":"cdk-textarea-autosize-measuring";r&&(e.style.marginBottom=`${e.clientHeight}px`),e.classList.add(o);const a=e.scrollHeight-4;return e.classList.remove(o),r&&(e.style.marginBottom=t),a}_cacheTextareaPlaceholderHeight(){if(!this._isViewInited||null!=this._cachedPlaceholderHeight)return;if(!this.placeholder)return void(this._cachedPlaceholderHeight=0);const e=this._textareaElement.value;this._textareaElement.value=this._textareaElement.placeholder,this._cachedPlaceholderHeight=this._measureScrollHeight(),this._textareaElement.value=e}ngDoCheck(){this._platform.isBrowser&&this.resizeToFitContent()}resizeToFitContent(e=!1){if(!this._enabled)return;if(this._cacheTextareaLineHeight(),this._cacheTextareaPlaceholderHeight(),!this._cachedLineHeight)return;const t=this._elementRef.nativeElement,n=t.value;if(!e&&this._minRows===this._previousMinRows&&n===this._previousValue)return;const r=this._measureScrollHeight(),o=Math.max(r,this._cachedPlaceholderHeight||0);t.style.height=`${o}px`,this._ngZone.runOutsideAngular((()=>{"undefined"!=typeof requestAnimationFrame?requestAnimationFrame((()=>this._scrollToCaretPosition(t))):setTimeout((()=>this._scrollToCaretPosition(t)))})),this._previousValue=n,this._previousMinRows=this._minRows}reset(){void 0!==this._initialHeight&&(this._textareaElement.style.height=this._initialHeight)}_noopInputHandler(){}_getDocument(){return this._document||document}_getWindow(){return this._getDocument().defaultView||window}_scrollToCaretPosition(e){const{selectionStart:t,selectionEnd:n}=e;!this._destroyed.isStopped&&this._hasFocus&&e.setSelectionRange(t,n)}}Vr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,deps:[{token:t.ElementRef},{token:dt.Platform},{token:t.NgZone},{token:$,optional:!0}],target:t.ɵɵFactoryTarget.Directive}),Vr.ɵdir=t.ɵɵngDeclareDirective({minVersion:"14.0.0",version:"15.2.0-rc.0",type:Vr,selector:"textarea[cdkTextareaAutosize]",inputs:{minRows:["cdkAutosizeMinRows","minRows"],maxRows:["cdkAutosizeMaxRows","maxRows"],enabled:["cdkTextareaAutosize","enabled"],placeholder:"placeholder"},host:{attributes:{rows:"1"},listeners:{input:"_noopInputHandler()"},classAttribute:"cdk-textarea-autosize"},exportAs:["cdkTextareaAutosize"],ngImport:t}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Vr,decorators:[{type:s,args:[{selector:"textarea[cdkTextareaAutosize]",exportAs:"cdkTextareaAutosize",host:{class:"cdk-textarea-autosize",rows:"1","(input)":"_noopInputHandler()"}}]}],ctorParameters:function(){return[{type:t.ElementRef},{type:dt.Platform},{type:t.NgZone},{type:void 0,decorators:[{type:i},{type:a,args:[$]}]}]},propDecorators:{minRows:[{type:m,args:["cdkAutosizeMinRows"]}],maxRows:[{type:m,args:["cdkAutosizeMaxRows"]}],enabled:[{type:m,args:["cdkTextareaAutosize"]}],placeholder:[{type:m}]}}); + /** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + class Pr{}Pr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Pr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),Pr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.0-rc.0",ngImport:t,type:Pr,declarations:[Dr,Vr],exports:[Dr,Vr]}),Pr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Pr}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.0-rc.0",ngImport:t,type:Pr,decorators:[{type:d,args:[{declarations:[Dr,Vr],exports:[Dr,Vr]}]}]});class Rr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.mailBodyTypes=[{name:"tb.mail-body-type.plain-text",description:"tb.mail-body-type.plain-text-description",value:"false"},{name:"tb.mail-body-type.html",description:"tb.mail-body-type.html-text-description",value:"true"},{name:"tb.mail-body-type.use-body-type-template",description:"tb.mail-body-type.dynamic-text-description",value:"dynamic"}]}configForm(){return this.toEmailConfigForm}onConfigurationSet(e){this.toEmailConfigForm=this.fb.group({fromTemplate:[e?e.fromTemplate:null,[_.required]],toTemplate:[e?e.toTemplate:null,[_.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[_.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[_.required]],bodyTemplate:[e?e.bodyTemplate:null,[_.required]]})}prepareInputConfig(e){return{fromTemplate:ye(e?.fromTemplate)?e.fromTemplate:null,toTemplate:ye(e?.toTemplate)?e.toTemplate:null,ccTemplate:ye(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:ye(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:ye(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:ye(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:ye(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:ye(e?.bodyTemplate)?e.bodyTemplate:null}}updateValidators(e){"dynamic"===this.toEmailConfigForm.get("mailBodyType").value?this.toEmailConfigForm.get("isHtmlTemplate").enable({emitEvent:!1}):this.toEmailConfigForm.get("isHtmlTemplate").disable({emitEvent:!1}),this.toEmailConfigForm.get("isHtmlTemplate").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["mailBodyType"]}getBodyTypeName(){return this.mailBodyTypes.find((e=>e.value===this.toEmailConfigForm.get("mailBodyType").value)).name}}e("ToEmailConfigComponent",Rr),Rr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Rr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Rr,selector:"tb-transformation-node-to-email-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:ue.HelpPopupComponent,selector:"[tb-help-popup], [tb-help-popup-content]",inputs:["tb-help-popup","tb-help-popup-content","trigger-text","trigger-style","tb-help-popup-placement","tb-help-popup-style","hintMode"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Vr,selector:"textarea[cdkTextareaAutosize]",inputs:["cdkAutosizeMinRows","cdkAutosizeMaxRows","cdkTextareaAutosize","placeholder"],exportAs:["cdkTextareaAutosize"]},{kind:"component",type:ne.MatSelect,selector:"mat-select",inputs:["disabled","disableRipple","tabIndex","hideSingleSelectionIndicator"],exportAs:["matSelect"]},{kind:"directive",type:ne.MatSelectTrigger,selector:"mat-select-trigger"},{kind:"component",type:re.MatOption,selector:"mat-option",exportAs:["matOption"]},{kind:"directive",type:Re.MatListItemTitle,selector:"[matListItemTitle]"},{kind:"directive",type:Re.MatListItemMeta,selector:"[matListItemMeta]"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Rr,decorators:[{type:n,args:[{selector:"tb-transformation-node-to-email-config",template:'
\n
\n
tb.rulenode.email-sender
\n
\n \n tb.rulenode.from-template\n \n \n {{ \'tb.rulenode.email-from-template-hint\' | translate }}\n \n \n
\n
\n
\n
\n \n {{ \'tb.rulenode.from-template-required\' | translate }}\n \n
\n
\n
\n
\n
\n
tb.rulenode.recipients
\n \n \n
\n
\n \n tb.rulenode.to-template\n \n \n {{ \'tb.rulenode.to-template-required\' | translate }}\n \n \n \n tb.rulenode.cc-template\n \n \n \n tb.rulenode.bcc-template\n \n \n
\n
\n
\n
tb.rulenode.message-subject-and-content
\n \n \n
\n \n tb.rulenode.subject-template\n \n \n {{ \'tb.rulenode.subject-template-required\' | translate }}\n \n \n \n tb.rulenode.mail-body-type\n \n \n \n {{ getBodyTypeName() | translate }}\n \n \n \n \n {{ type.name | translate }}\n \n
\n \n {{ type.description | translate }}\n \n
\n
\n
\n \n tb.rulenode.body-type-template\n \n tb.mail-body-type.after-template-evaluation-hint\n \n \n tb.rulenode.body-template\n \n \n {{ \'tb.rulenode.body-template-required\' | translate }}\n \n \n
\n
\n
\n',styles:[":host .input-bottom-double-hint{display:inline-flex}:host .input-bottom-double-hint .see-example{flex-shrink:0;padding-right:16px}:host textarea.tb-enable-vertical-resize{resize:vertical}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Or extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=mn;for(const e of this.translation.keys())this.copyFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.copyKeysConfigForm=this.fb.group({copyFrom:[e.copyFrom,[_.required]],keys:[e?e.keys:null,[_.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=ye(e?.fromMetadata)?e.copyFrom?sn.METADATA:sn.DATA:ye(e?.copyFrom)?e.copyFrom:sn.DATA,{keys:ye(e?.keys)?e.keys:null,copyFrom:t}}}e("CopyKeysConfigComponent",Or),Or.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Or.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Or,selector:"tb-transformation-node-copy-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Or,decorators:[{type:n,args:[{selector:"tb-transformation-node-copy-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class _r extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=dn;for(const e of this.translation.keys())this.renameIn.push({value:e,name:this.translate.instant(this.translation.get(e))})}configForm(){return this.renameKeysConfigForm}onConfigurationSet(e){this.renameKeysConfigForm=this.fb.group({renameIn:[e?e.renameIn:null,[_.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[_.required]]})}prepareInputConfig(e){let t;return t=ye(e?.fromMetadata)?e.fromMetadata?sn.METADATA:sn.DATA:ye(e?.renameIn)?e?.renameIn:sn.DATA,{renameKeysMapping:ye(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}}e("RenameKeysConfigComponent",_r),_r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),_r.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:_r,selector:"tb-transformation-node-rename-keys-config",usesInheritance:!0,ngImport:t,template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Rn,selector:"tb-kv-map-config",inputs:["disabled","uniqueKeyValuePairValidator","labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText","popupHelpLink","required"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:_r,decorators:[{type:n,args:[{selector:"tb-transformation-node-rename-keys-config",template:'
\n
tb.rulenode.rename-keys-in
\n
\n
\n \n \n {{ data.name }}\n \n \n
\n
\n \n \n
\n',styles:[":host .fetch-to-data-toggle{max-width:420px;width:100%}:host .fx-centered{display:flex;width:100%;justify-content:space-around}\n"]}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class Br extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.jsonPathConfigForm}onConfigurationSet(e){this.jsonPathConfigForm=this.fb.group({jsonPath:[e?e.jsonPath:null,[_.required]]})}}e("NodeJsonPathConfigComponent",Br),Br.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Br.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Br,selector:"tb-transformation-node-json-path-config",usesInheritance:!0,ngImport:t,template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n",dependencies:[{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatHint,selector:"mat-hint",inputs:["align","id"]},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Br,decorators:[{type:n,args:[{selector:"tb-transformation-node-json-path-config",template:"
\n \n {{ 'tb.rulenode.json-path-expression' | translate }}\n \n {{ 'tb.rulenode.json-path-expression-hint' | translate }}\n {{ 'tb.rulenode.json-path-expression-required' | translate }}\n \n
\n"}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class Kr extends g{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=pn;for(const e of this.translation.keys())this.deleteFrom.push({value:e,name:this.translate.instant(this.translation.get(e))})}onConfigurationSet(e){this.deleteKeysConfigForm=this.fb.group({deleteFrom:[e.deleteFrom,[_.required]],keys:[e?e.keys:null,[_.required]]})}prepareInputConfig(e){let t;return t=ye(e?.fromMetadata)?e.fromMetadata?sn.METADATA:sn.DATA:ye(e?.deleteFrom)?e?.deleteFrom:sn.DATA,{keys:ye(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}}e("DeleteKeysConfigComponent",Kr),Kr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,deps:[{token:R.Store},{token:O.FormBuilder},{token:X.TranslateService}],target:t.ɵɵFactoryTarget.Component}),Kr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Kr,selector:"tb-transformation-node-delete-keys-config",usesInheritance:!0,ngImport:t,template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"component",type:tt.StringItemsListComponent,selector:"tb-string-items-list",inputs:["required","disabled","label","placeholder","hint","requiredText","floatLabel","appearance","editable","subscriptSizing","predefinedValues"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:zn,selector:"tb-msg-metadata-chip",inputs:["labelText","translation"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Kr,decorators:[{type:n,args:[{selector:"tb-transformation-node-delete-keys-config",template:'
\n \n \n \n \n help\n \n \n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder},{type:X.TranslateService}]}});class Hr extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=_t,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Bt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[ye(e?.interval)?e.interval:null,[_.required,_.min(1)]],strategy:[ye(e?.strategy)?e.strategy:null,[_.required]],outMsgType:[ye(e?.outMsgType)?e.outMsgType:null,[_.required]],maxPendingMsgs:[ye(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[_.required,_.min(1),_.max(1e3)]],maxRetries:[ye(e?.maxRetries)?e.maxRetries:null,[_.required,_.min(0),_.max(100)]]})}prepareInputConfig(e){return e||(e={}),e.outMsgType||(e.outMsgType="POST_TELEMETRY_REQUEST"),super.prepareInputConfig(e)}updateValidators(e){this.deduplicationConfigForm.get("strategy").value===this.deduplicationStrategie.ALL?this.deduplicationConfigForm.get("outMsgType").enable({emitEvent:!1}):this.deduplicationConfigForm.get("outMsgType").disable({emitEvent:!1}),this.deduplicationConfigForm.get("outMsgType").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["strategy"]}}e("DeduplicationConfigComponent",Hr),Hr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,deps:[{token:R.Store},{token:O.FormBuilder}],target:t.ɵɵFactoryTarget.Component}),Hr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Hr,selector:"tb-action-node-msg-deduplication-config",usesInheritance:!0,ngImport:t,template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n'],dependencies:[{kind:"directive",type:j.NgForOf,selector:"[ngFor][ngForOf]",inputs:["ngForOf","ngForTrackBy","ngForTemplate"]},{kind:"directive",type:j.NgIf,selector:"[ngIf]",inputs:["ngIf","ngIfThen","ngIfElse"]},{kind:"component",type:te.MatIcon,selector:"mat-icon",inputs:["color","inline","svgIcon","fontSet","fontIcon"],exportAs:["matIcon"]},{kind:"directive",type:Q.MatInput,selector:"input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]",inputs:["disabled","id","placeholder","name","required","type","errorStateMatcher","aria-describedby","value","readonly"],exportAs:["matInput"]},{kind:"component",type:Y.MatFormField,selector:"mat-form-field",inputs:["hideRequiredMarker","color","floatLabel","appearance","subscriptSizing","hintLabel"],exportAs:["matFormField"]},{kind:"directive",type:Y.MatLabel,selector:"mat-label"},{kind:"directive",type:Y.MatError,selector:"mat-error, [matError]",inputs:["id"]},{kind:"directive",type:Y.MatSuffix,selector:"[matSuffix], [matIconSuffix], [matTextSuffix]",inputs:["matTextSuffix"]},{kind:"directive",type:oe.MatTooltip,selector:"[matTooltip]",exportAs:["matTooltip"]},{kind:"component",type:ae.MatExpansionPanel,selector:"mat-expansion-panel",inputs:["disabled","expanded","hideToggle","togglePosition"],outputs:["opened","closed","expandedChange","afterExpand","afterCollapse"],exportAs:["matExpansionPanel"]},{kind:"component",type:ae.MatExpansionPanelHeader,selector:"mat-expansion-panel-header",inputs:["tabIndex","expandedHeight","collapsedHeight"]},{kind:"directive",type:ae.MatExpansionPanelTitle,selector:"mat-panel-title"},{kind:"directive",type:O.DefaultValueAccessor,selector:"input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]"},{kind:"directive",type:O.NumberValueAccessor,selector:"input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]"},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"directive",type:X.TranslateDirective,selector:"[translate],[ngx-translate]",inputs:["translate","translateParams"]},{kind:"directive",type:Me.ToggleOption,selector:"tb-toggle-option",inputs:["value"]},{kind:"component",type:Ee.ToggleSelectComponent,selector:"tb-toggle-select",inputs:["disabled","selectMediaBreakpoint","appearance","disablePagination","fillHeight","extraPadding","primaryBackground"]},{kind:"component",type:Hn,selector:"tb-output-message-type-autocomplete",inputs:["subscriptSizing","disabled","required"]},{kind:"component",type:ht,selector:"tb-example-hint",inputs:["hintText","popupHelpLink","textAlign"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Hr,decorators:[{type:n,args:[{selector:"tb-action-node-msg-deduplication-config",template:'
\n \n {{\'tb.rulenode.interval\' | translate}}\n \n \n {{\'tb.rulenode.interval-required\' | translate}}\n \n \n {{\'tb.rulenode.interval-min-error\' | translate}}\n \n help\n \n
\n
\n
tb.rulenode.strategy
\n \n \n {{ deduplicationStrategiesTranslations.get(strategy) | translate }}\n \n \n \n \n \n \n \n \n
\n \n \n
\n
\n
\n \n \n tb.rulenode.advanced-settings\n \n
\n \n {{\'tb.rulenode.max-pending-msgs\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-required\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-pending-msgs-min-error\' | translate}}\n \n help\n \n \n {{\'tb.rulenode.max-retries\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-required\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-max-error\' | translate}}\n \n \n {{\'tb.rulenode.max-retries-min-error\' | translate}}\n \n help\n \n
\n
\n
\n
\n
\n',styles:[':host .margin-8{margin:8px}:host .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}:host .tb-required:after{content:"*";font-size:16px;color:#000000de}:host .help-icon{color:#000;opacity:.38;padding:unset}:host .help-icon:hover{color:#305680;opacity:unset}.same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.same-width-component-row{gap:8px}}.same-width-component-row>*{flex:1}\n']}]}],ctorParameters:function(){return[{type:R.Store},{type:O.FormBuilder}]}});class zr{}e("RulenodeCoreConfigTransformModule",zr),zr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,deps:[],target:t.ɵɵFactoryTarget.NgModule}),zr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:zr,declarations:[Mr,Er,Rr,Or,_r,Br,Kr,Hr],imports:[J,E,Qn],exports:[Mr,Er,Rr,Or,_r,Br,Kr,Hr]}),zr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,imports:[J,E,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:zr,decorators:[{type:d,args:[{declarations:[Mr,Er,Rr,Or,_r,Br,Kr,Hr],imports:[J,E,Qn],exports:[Mr,Er,Rr,Or,_r,Br,Kr,Hr]}]}]});class Ur extends g{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=C}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({forwardMsgToDefaultRuleChain:[!!e&&e?.forwardMsgToDefaultRuleChain,[]],ruleChainId:[e?e.ruleChainId:null,[_.required]]})}}e("RuleChainInputComponent",Ur),Ur.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),Ur.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:Ur,selector:"tb-flow-node-rule-chain-input-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n \n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n \n
\n \n \n
\n
\n',dependencies:[{kind:"component",type:st.EntityAutocompleteComponent,selector:"tb-entity-autocomplete",inputs:["entityType","entitySubtype","excludeEntityIds","labelText","requiredText","useFullEntityId","appearance","required","disabled"],outputs:["entityChanged"]},{kind:"component",type:W.MatSlideToggle,selector:"mat-slide-toggle",inputs:["disabled","disableRipple","color","tabIndex"],exportAs:["matSlideToggle"]},{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.NgControlStatus,selector:"[formControlName],[ngModel],[formControl]"},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.RequiredValidator,selector:":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]",inputs:["required"]},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"directive",type:O.FormControlName,selector:"[formControlName]",inputs:["formControlName","disabled","ngModel"],outputs:["ngModelChange"]},{kind:"component",type:de.HintTooltipIconComponent,selector:"[tb-hint-tooltip-icon]",inputs:["tb-hint-tooltip-icon","tooltipPosition","hintIcon"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Ur,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-input-config",template:'
\n
\n
\n \n {{ \'tb.rulenode.forward-msg-default-rule-chain\' | translate }}\n \n
\n \n \n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class jr extends g{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}}e("RuleChainOutputComponent",jr),jr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,deps:[{token:R.Store},{token:O.UntypedFormBuilder}],target:t.ɵɵFactoryTarget.Component}),jr.ɵcmp=t.ɵɵngDeclareComponent({minVersion:"14.0.0",version:"15.2.10",type:jr,selector:"tb-flow-node-rule-chain-output-config",usesInheritance:!0,ngImport:t,template:'
\n
\n
\n',dependencies:[{kind:"directive",type:Z.DefaultLayoutDirective,selector:" [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]",inputs:["fxLayout","fxLayout.xs","fxLayout.sm","fxLayout.md","fxLayout.lg","fxLayout.xl","fxLayout.lt-sm","fxLayout.lt-md","fxLayout.lt-lg","fxLayout.lt-xl","fxLayout.gt-xs","fxLayout.gt-sm","fxLayout.gt-md","fxLayout.gt-lg"]},{kind:"directive",type:O.NgControlStatusGroup,selector:"[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]"},{kind:"directive",type:O.FormGroupDirective,selector:"[formGroup]",inputs:["formGroup"],outputs:["ngSubmit"],exportAs:["ngForm"]},{kind:"pipe",type:X.TranslatePipe,name:"translate"}]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:jr,decorators:[{type:n,args:[{selector:"tb-flow-node-rule-chain-output-config",template:'
\n
\n
\n'}]}],ctorParameters:function(){return[{type:R.Store},{type:O.UntypedFormBuilder}]}});class $r{}e("RuleNodeCoreConfigFlowModule",$r),$r.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,deps:[],target:t.ɵɵFactoryTarget.NgModule}),$r.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:$r,declarations:[Ur,jr],imports:[J,E,Qn],exports:[Ur,jr]}),$r.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,imports:[J,E,Qn]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:$r,decorators:[{type:d,args:[{declarations:[Ur,jr],imports:[J,E,Qn],exports:[Ur,jr]}]}]});class Jr{constructor(e){!function(e){e.setTranslation("en_US",{tb:{rulenode:{id:"Id","additional-info":"Additional Info","advanced-settings":"Advanced settings","create-entity-if-not-exists":"Create new entity if it doesn't exist","create-entity-if-not-exists-hint":"If enabled, a new entity with specified parameters will be created unless it already exists. Existing entities will be used as is for relation.","select-device-connectivity-event":"Select device connectivity event","entity-name-pattern":"Name pattern","device-name-pattern":"Device name","asset-name-pattern":"Asset name","entity-view-name-pattern":"Entity view name","customer-title-pattern":"Customer title","dashboard-name-pattern":"Dashboard title","user-name-pattern":"User email","edge-name-pattern":"Edge name","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","copy-message-type":"Copy message type","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","message-type-value":"Message type value","message-type-value-required":"Message type value is required","message-type-value-max-length":"Message type value should be less than 256","output-message-type":"Output message type","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer title","customer-name-pattern-required":"Customer title is required","customer-name-pattern-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","create-customer-if-not-exists":"Create new customer if it doesn't exist","unassign-from-customer":"Unassign from specific customer if originator is dashboard","unassign-from-customer-tooltip":"Only dashboards can be assigned to multiple customers at once. \nIf the message originator is a dashboard, you need to explicitly specify the customer's title to unassign from.","customer-cache-expiration":"Customers cache expiration time (sec)","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","interval-start":"Interval start","interval-end":"Interval end","time-unit":"Time unit","fetch-mode":"Fetch mode","order-by-timestamp":"Order by timestamp",limit:"Limit","limit-hint":"Min limit value is 2, max - 1000. If you want to fetch a single entry, select fetch mode 'First' or 'Last'.","limit-required":"Limit is required.","limit-range":"Limit should be in a range from 2 to 1000.","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Allowing range from 1 to 2147483647.","start-interval-value-required":"Interval start is required.","end-interval-value-required":"Interval end is required.",filter:"Filter",switch:"Switch","math-templatization-tooltip":"This field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","add-message-type":"Add message type","select-message-types-required":"At least one message type should be selected.","select-message-types":"Select message types","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one.","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","attributes-keys":"Attributes keys","attributes-keys-required":"Attributes keys are required","attributes-scope":"Attributes scope","attributes-scope-value":"Attributes scope value","attributes-scope-value-copy":"Copy attributes scope value","attributes-scope-hint":"Use the 'scope' metadata key to dynamically set the attribute scope per message. If provided, this overrides the scope set in the configuration.","notify-device":"Force notification to the device","send-attributes-updated-notification":"Send attributes updated notification","send-attributes-updated-notification-hint":"Send notification about updated attributes as a separate message to the rule engine queue.","send-attributes-deleted-notification":"Send attributes deleted notification","send-attributes-deleted-notification-hint":"Send notification about deleted attributes as a separate message to the rule engine queue.","update-attributes-only-on-value-change":"Save attributes only if the value changes","update-attributes-only-on-value-change-hint":"Updates the attributes on every incoming message disregarding if their value has changed. Increases API usage and reduces performance.","update-attributes-only-on-value-change-hint-enabled":"Updates the attributes only if their value has changed. If the value is not changed, no update to the attribute timestamp nor attribute change notification will be sent.","fetch-credentials-to-metadata":"Fetch credentials to metadata","notify-device-on-update-hint":"If enabled, force notification to the device about shared attributes update. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn off the notification, the message metadata must contain the 'notifyDevice' parameter set to 'false'. Any other case will trigger the notification to the device.","notify-device-on-delete-hint":"If enabled, force notification to the device about shared attributes removal. If disabled, the notification behavior is controlled by the 'notifyDevice' parameter from the incoming message metadata. To turn on the notification, the message metadata must contain the 'notifyDevice' parameter set to 'true'. In any other case, the notification will not be triggered to the device.","latest-timeseries":"Latest time series data keys","timeseries-keys":"Time series keys","timeseries-keys-required":"At least one time series key should be selected.","add-timeseries-key":"Add time series key","add-message-field":"Add message field","relation-search-parameters":"Relation search parameters","relation-parameters":"Relation parameters","add-metadata-field":"Add metadata field","data-keys":"Message field names","copy-from":"Copy from","data-to-metadata":"Data to metadata","metadata-to-data":"Metadata to data","use-regular-expression-hint":"Use regular expression to copy keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name. Multiple field names supported.",interval:"Interval","interval-required":"Interval is required","interval-hint":"Deduplication interval in seconds.","interval-min-error":"Min allowed value is 1","max-pending-msgs":"Max pending messages","max-pending-msgs-hint":"Maximum number of messages that are stored in memory for each unique deduplication id.","max-pending-msgs-required":"Max pending messages is required","max-pending-msgs-max-error":"Max allowed value is 1000","max-pending-msgs-min-error":"Min allowed value is 1","max-retries":"Max retries","max-retries-required":"Max retries is required","max-retries-hint":"Maximum number of retries to push the deduplicated messages into the queue. 10 seconds delay is used between retries","max-retries-max-error":"Max allowed value is 100","max-retries-min-error":"Min allowed value is 0",strategy:"Strategy","strategy-required":"Strategy is required","strategy-all-hint":"Return all messages that arrived during deduplication period as a single JSON array message. Where each element represents object with msg and metadata inner properties.","strategy-first-hint":"Return first message that arrived during deduplication period.","strategy-last-hint":"Return last message that arrived during deduplication period.",first:"First",last:"Last",all:"All","output-msg-type-hint":"The message type of the deduplication result.","queue-name-hint":"The queue name where the deduplication result will be published.",keys:"Keys","keys-required":"Keys are required","rename-keys-in":"Rename keys in",data:"Data",message:"Message",metadata:"Metadata","current-key-name":"Current key name","key-name-required":"Key name is required","new-key-name":"New key name","new-key-name-required":"New key name is required","metadata-keys":"Metadata field names","json-path-expression":"JSON path expression","json-path-expression-required":"JSON path expression is required","json-path-expression-hint":"JSONPath specifies a path to an element or a set of elements in a JSON structure. '$' represents the root object or array.","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","max-relation-level-error":"Value should be greater than 0 or unspecified.","relation-type":"Relation type","relation-type-pattern":"Relation type pattern","relation-type-pattern-required":"Relation type pattern is required","relation-types-list":"Relation types to propagate","relation-types-list-hint":"If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","add-telemetry-key":"Add telemetry key","delete-from":"Delete from","use-regular-expression-delete-hint":"Use regular expression to delete keys by pattern.\n\nTips & tricks:\nPress 'Enter' to complete field name input.\nPress 'Backspace' to delete field name.\nMultiple field names supported.","fetch-into":"Fetch into","attr-mapping":"Attributes mapping:","source-attribute":"Source attribute key","source-attribute-required":"Source attribute key is required.","source-telemetry":"Source telemetry key","source-telemetry-required":"Source telemetry key is required.","target-key":"Target key","target-key-required":"Target key is required.","attr-mapping-required":"At least one mapping entry should be specified.","fields-mapping":"Fields mapping","relations-query-config-direction-suffix":"originator","profile-name":"Profile name","fetch-circle-parameter-info-from-metadata-hint":'Metadata field \'{{perimeterKeyName}}\' should be defined in next format: {"latitude":48.196, "longitude":24.6532, "radius":100.0, "radiusUnit":"METER"}',"fetch-poligon-parameter-info-from-metadata-hint":"Metadata field '{{perimeterKeyName}}' should be defined in next format: [[48.19736,24.65235],[48.19800,24.65060],...,[48.19849,24.65420]]","short-templatization-tooltip":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","fields-mapping-required":"At least one field mapping should be specified.","at-least-one-field-required":"At least one input field must have a value(s) provided.","originator-fields-sv-map-hint":"Target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","sv-map-hint":"Only target key fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","new-originator":"New originator","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related entity","originator-alarm-originator":"Alarm Originator","originator-entity":"Entity by name pattern","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","default-ttl-hint":"Rule node will fetch Time-to-Live (TTL) value from the message metadata. If no value is present, it defaults to the TTL specified in the configuration. If the value is set to 0, the TTL from the tenant profile configuration will be applied.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","generation-parameters":"Generation parameters","message-count":"Generated messages limit (0 - unlimited)","message-count-required":"Generated messages limit is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Generation frequency in seconds","period-seconds-required":"Period is required.","script-lang-tbel":"TBEL","script-lang-js":"JS","use-metadata-period-in-seconds-patterns":"Use period in seconds pattern","use-metadata-period-in-seconds-patterns-hint":"If selected, rule node use period in seconds interval pattern from message metadata or data assuming that intervals are in the seconds.","period-in-seconds-pattern":"Period in seconds pattern","period-in-seconds-pattern-required":"Period in seconds pattern is required","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","current-rule-node":"Current Rule Node","generator-function":"Generator function","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","select-entity-types":"Select entity types","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required","alarm-severity-pattern":"Alarm severity pattern","alarm-status-filter":"Alarm status filter","alarm-status-list-empty":"Alarm status list is empty","no-alarm-status-matching":"No alarm status matching were found.",propagate:"Propagate alarm to related entities","propagate-to-owner":"Propagate alarm to entity owner (Customer or Tenant)","propagate-to-tenant":"Propagate alarm to Tenant",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From","from-template-required":"From is required","message-to-metadata":"Message to metadata","metadata-to-message":"Metadata to message","from-message":"From message","from-metadata":"From metadata","to-template":"To","to-template-required":"To Template is required","mail-address-list-template-hint":'Comma separated address list, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"cc-template":"Cc","bcc-template":"Bcc","subject-template":"Subject","subject-template-required":"Subject Template is required","body-template":"Body","body-template-required":"Body Template is required","dynamic-mail-body-type":"Dynamic mail body type","mail-body-type":"Mail body type","body-type-template":"Body type template","reply-routing-configuration":"Reply Routing Configuration","rpc-reply-routing-configuration-hint":"These configuration parameters specify the metadata key names used to identify the service, session, and request for sending a reply back.","reply-routing-configuration-hint":"These configuration parameters specify the metadata key names used to identify the service and request for sending a reply back.","request-id-metadata-attribute":"Request Id","service-id-metadata-attribute":"Service Id","session-id-metadata-attribute":"Session Id","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","request-method":"Request method","use-simple-client-http-factory":"Use simple client HTTP factory","ignore-request-body":"Without request body","parse-to-plain-text":"Parse to plain text","parse-to-plain-text-hint":'If selected, request body message payload will be transformed from JSON string to plain text, e.g. msg = "Hello,\\t\\"world\\"" will be parsed to Hello, "world"',"read-timeout":"Read timeout in millis","read-timeout-hint":"The value of 0 means an infinite timeout","max-parallel-requests-count":"Max number of parallel requests","max-parallel-requests-count-hint":"The value of 0 specifies no limit in parallel processing","max-response-size":"Max response size (in KB)","max-response-size-hint":"The maximum amount of memory allocated for buffering data when decoding or encoding HTTP messages, such as JSON or XML payloads",headers:"Headers","headers-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in header/value fields',header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","key-pattern":"Key pattern","key-pattern-hint":"Optional. If a valid partition number is specified, it will be used when sending the record. If no partition is specified, the key will be used instead. If neither is specified, a partition will be assigned in a round-robin fashion.","topic-pattern-required":"Topic pattern is required",topic:"Topic","topic-required":"Topic is required","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","gcp-project-id":"GCP project ID","gcp-project-id-required":"GCP project ID is required","gcp-service-account-key":"GCP service account key file","gcp-service-account-key-required":"GCP service account key file is required","pubsub-topic-name":"Topic name","pubsub-topic-name-required":"Topic name is required","message-attributes":"Message attributes","message-attributes-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body in name/value fields',"connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","client-id-hint":'Optional. Leave empty for auto-generated Client ID. Be careful when specifying the Client ID. Majority of the MQTT brokers will not allow multiple connections with the same Client ID. To connect to such brokers, your mqtt Client ID must be unique. When platform is running in a micro-services mode, the copy of rule node is launched in each micro-service. This will automatically lead to multiple mqtt clients with the same ID and may cause failures of the rule node. To avoid such failures enable "Add Service ID as suffix to Client ID" option below.',"append-client-id-suffix":"Add Service ID as suffix to Client ID","client-id-suffix-hint":'Optional. Applied when "Client ID" specified explicitly. If selected then Service ID will be added to Client ID as a suffix. Helps to avoid failures when platform is running in a micro-services mode.',"device-id":"Device ID","device-id-required":"Device ID is required.","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","credentials-pem-hint":"At least Server CA certificate file or a pair of Client certificate and Client private key files are required","credentials-sas":"Shared Access Signature","sas-key":"SAS Key","sas-key-required":"SAS Key is required.",hostname:"Hostname","hostname-required":"Hostname is required.","azure-ca-cert":"CA certificate file","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"Server CA certificate file","private-key":"Client private key file",cert:"Client certificate file","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-dynamic-interval":"Use dynamic interval","metadata-dynamic-interval-hint":"Interval start and end input fields support templatization. Note that the substituted template value should be set in milliseconds. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","use-metadata-interval-patterns-hint":"If selected, rule node use start and end interval patterns from message metadata or data assuming that intervals are in the milliseconds.","use-message-alarm-data":"Use message alarm data","overwrite-alarm-details":"Overwrite alarm details","use-alarm-severity-pattern":"Use alarm severity pattern","check-all-keys":"Check that all specified fields are present","check-all-keys-hint":"If selected, checks that all specified keys are present in the message data and metadata.","check-relation-to-specific-entity":"Check relation to specific entity","check-relation-to-specific-entity-tooltip":"If enabled, checks the presence of relation with a specific entity otherwise, checks the presence of relation with any entity. In both cases, relation lookup is based on configured direction and type.","check-relation-hint":"Checks existence of relation to specific entity or to any entity based on direction and relation type.","delete-relation-with-specific-entity":"Delete relation with specific entity","delete-relation-with-specific-entity-hint":"If enabled, will delete the relation with just one specific entity. Otherwise, the relation will be removed with all matching entities.","delete-relation-hint":"Deletes relation from the originator of the incoming message to the specified entity or list of entities based on direction and type.","remove-current-relations":"Remove current relations","remove-current-relations-hint":"Removes current relations from the originator of the incoming message based on direction and type.","change-originator-to-related-entity":"Change originator to related entity","change-originator-to-related-entity-hint":"Used to process submitted message as a message from another entity.","start-interval":"Interval start","end-interval":"Interval end","start-interval-required":"Interval start is required.","end-interval-required":"Interval end is required.","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","tls-version":"TLS version","enable-proxy":"Enable proxy","use-system-proxy-properties":"Use system proxy properties","proxy-host":"Proxy host","proxy-host-required":"Proxy host is required.","proxy-port":"Proxy port","proxy-port-required":"Proxy port is required.","proxy-port-range":"Proxy port should be in a range from 1 to 65535.","proxy-user":"Proxy user","proxy-password":"Proxy password","proxy-scheme":"Proxy scheme","numbers-to-template":"Phone Numbers To Template","numbers-to-template-required":"Phone Numbers To Template is required","numbers-to-template-hint":'Comma separated Phone Numbers, use ${metadataKey} for value from metadata, $[messageKey] for value from message body',"sms-message-template":"SMS message Template","sms-message-template-required":"SMS message Template is required","use-system-sms-settings":"Use system SMS provider settings","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output time series key prefix","output-timeseries-key-prefix-required":"Output time series key prefix required.","separator-hint":'Press "Enter" to complete field input.',"select-details":"Select details","entity-details-id":"Id","entity-details-title":"Title","entity-details-country":"Country","entity-details-state":"State","entity-details-city":"City","entity-details-zip":"Zip","entity-details-address":"Address","entity-details-address2":"Address2","entity-details-additional_info":"Additional Info","entity-details-phone":"Phone","entity-details-email":"Email","email-sender":"Email sender","fields-to-check":"Fields to check","add-detail":"Add detail","check-all-keys-tooltip":"If enabled, checks the presence of all fields listed in the message and metadata field names within the incoming message and its metadata.","fields-to-check-hint":'Press "Enter" to complete field name input. Multiple field names supported.',"entity-details-list-empty":"At least one detail should be selected.","alarm-status":"Alarm status","alarm-required":"At least one alarm status should be selected.","no-entity-details-matching":"No entity details matching were found.","custom-table-name":"Custom table name","custom-table-name-required":"Table Name is required","custom-table-hint":"Enter the table name without prefix 'cs_tb_'.","message-field":"Message field","message-field-required":"Message field is required.","table-col":"Table column","table-col-required":"Table column is required.","latitude-field-name":"Latitude field name","longitude-field-name":"Longitude field name","latitude-field-name-required":"Latitude field name is required.","longitude-field-name-required":"Longitude field name is required.","fetch-perimeter-info-from-metadata":"Fetch perimeter information from metadata","fetch-perimeter-info-from-metadata-tooltip":"If perimeter type is set to 'Polygon' the value of metadata field '{{perimeterKeyName}}' will be set as perimeter definition without additional parsing of the value. Otherwise, if perimeter type is set to 'Circle' the value of '{{perimeterKeyName}}' metadata field will be parsed to extract 'latitude', 'longitude', 'radius', 'radiusUnit' fields that uses for circle perimeter definition.","perimeter-key-name":"Perimeter key name","perimeter-key-name-hint":"Metadata field name that includes perimeter information.","perimeter-key-name-required":"Perimeter key name is required.","perimeter-circle":"Circle","perimeter-polygon":"Polygon","perimeter-type":"Perimeter type","circle-center-latitude":"Center latitude","circle-center-latitude-required":"Center latitude is required.","circle-center-longitude":"Center longitude","circle-center-longitude-required":"Center longitude is required.","range-unit-meter":"Meter","range-unit-kilometer":"Kilometer","range-unit-foot":"Foot","range-unit-mile":"Mile","range-unit-nautical-mile":"Nautical mile","range-units":"Range units","range-units-required":"Range units is required.",range:"Range","range-required":"Range is required.","polygon-definition":"Polygon definition","polygon-definition-required":"Polygon definition is required.","polygon-definition-hint":"Use the following format for manual definition of polygon: [[lat1,lon1],[lat2,lon2], ... ,[latN,lonN]].","min-inside-duration":"Minimal inside duration","min-inside-duration-value-required":"Minimal inside duration is required","min-inside-duration-time-unit":"Minimal inside duration time unit","min-outside-duration":"Minimal outside duration","min-outside-duration-value-required":"Minimal outside duration is required","min-outside-duration-time-unit":"Minimal outside duration time unit","tell-failure-if-absent":"Tell Failure","tell-failure-if-absent-hint":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"get-latest-value-with-ts":"Fetch timestamp for the latest telemetry values","get-latest-value-with-ts-hint":'If selected, the latest telemetry values will also include timestamp, e.g: "temp": "{"ts":1574329385897, "value":42}"',"ignore-null-strings":"Ignore null strings","ignore-null-strings-hint":"If selected rule node will ignore entity fields with empty value.","add-metadata-key-values-as-kafka-headers":"Add Message metadata key-value pairs to Kafka record headers","add-metadata-key-values-as-kafka-headers-hint":"If selected, key-value pairs from message metadata will be added to the outgoing records headers as byte arrays with predefined charset encoding.","charset-encoding":"Charset encoding","charset-encoding-required":"Charset encoding is required.","charset-us-ascii":"US-ASCII","charset-iso-8859-1":"ISO-8859-1","charset-utf-8":"UTF-8","charset-utf-16be":"UTF-16BE","charset-utf-16le":"UTF-16LE","charset-utf-16":"UTF-16","select-queue-hint":"The queue name can be selected from a drop-down list or add a custom name.","device-profile-node-hint":"Useful if you have duration or repeating conditions to ensure continuity of alarm state evaluation.","persist-alarm-rules":"Persist state of alarm rules","persist-alarm-rules-hint":"If enabled, the rule node will store the state of processing to the database.","fetch-alarm-rules":"Fetch state of alarm rules","fetch-alarm-rules-hint":"If enabled, the rule node will restore the state of processing on initialization and ensure that alarms are raised even after server restarts. Otherwise, the state will be restored when the first message from the device arrives.","input-value-key":"Input value key","input-value-key-required":"Input value key is required.","output-value-key":"Output value key","output-value-key-required":"Output value key is required.","number-of-digits-after-floating-point":"Number of digits after floating point","number-of-digits-after-floating-point-range":"Number of digits after floating point should be in a range from 0 to 15.","failure-if-delta-negative":"Tell Failure if delta is negative","failure-if-delta-negative-tooltip":"Rule node forces failure of message processing if delta value is negative.","use-caching":"Use caching","use-caching-tooltip":'Rule node will cache the value of "{{inputValueKey}}" that arrives from the incoming message to improve performance. Note that the cache will not be updated if you modify the "{{inputValueKey}}" value elsewhere.',"add-time-difference-between-readings":'Add the time difference between "{{inputValueKey}}" readings',"add-time-difference-between-readings-tooltip":'If enabled, the rule node will add the "{{periodValueKey}}" to the outbound message.',"period-value-key":"Period value key","period-value-key-required":"Period value key is required.","general-pattern-hint":"Use ${metadataKey} for value from metadata, $[messageKey] for value from message body.","alarm-severity-pattern-hint":'Use ${metadataKey} for value from metadata, $[messageKey] for value from message body. Alarm severity should be system (CRITICAL, MAJOR etc.)',"output-node-name-hint":"The rule node name corresponds to the relation type of the output message, and it is used to forward messages to other rule nodes in the caller rule chain.","skip-latest-persistence":"Skip latest persistence","skip-latest-persistence-hint":"Rule node will not update values for incoming keys for the latest time series data. Useful for highly loaded use-cases to decrease the pressure on the DB.","use-server-ts":"Use server ts","use-server-ts-hint":"Rule node will use the timestamp of message processing instead of the timestamp from the message. Useful for all sorts of sequential processing if you merge messages from multiple sources (devices, assets, etc).","kv-map-pattern-hint":"All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","kv-map-single-pattern-hint":"Input field support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","shared-scope":"Shared scope","server-scope":"Server scope","client-scope":"Client scope","attribute-type":"Attribute","constant-type":"Constant","time-series-type":"Time series","message-body-type":"Message","message-metadata-type":"Metadata","argument-tile":"Arguments","no-arguments-prompt":"No arguments configured","result-title":"Result","functions-field-input":"Functions","no-option-found":"No option found","argument-source-field-input":"Source","argument-source-field-input-required":"Argument source is required.","argument-key-field-input":"Key","argument-key-field-input-required":"Argument key is required.","constant-value-field-input":"Constant value","constant-value-field-input-required":"Constant value is required.","attribute-scope-field-input":"Attribute scope","attribute-scope-field-input-required":"Attribute scope os required.","default-value-field-input":"Default value","type-field-input":"Type","type-field-input-required":"Type is required.","key-field-input":"Key","add-entity-type":"Add entity type","add-device-profile":"Add device profile","key-field-input-required":"Key is required.","number-floating-point-field-input":"Number of digits after floating point","number-floating-point-field-input-hint":"Use 0 to convert result to integer","add-to-message-field-input":"Add to message","add-to-metadata-field-input":"Add to metadata","custom-expression-field-input":"Mathematical Expression","custom-expression-field-input-required":"Mathematical expression is required","custom-expression-field-input-hint":"Specify a mathematical expression to evaluate. Default expression demonstrates how to transform Fahrenheit to Celsius","retained-message":"Retained","attributes-mapping":"Attributes mapping","latest-telemetry-mapping":"Latest telemetry mapping","add-mapped-attribute-to":"Add mapped attributes to","add-mapped-latest-telemetry-to":"Add mapped latest telemetry to","add-mapped-fields-to":"Add mapped fields to","add-selected-details-to":"Add selected details to","clear-selected-types":"Clear selected types","clear-selected-details":"Clear selected details","clear-selected-fields":"Clear selected fields","clear-selected-keys":"Clear selected keys","geofence-configuration":"Geofence configuration","coordinate-field-names":"Coordinate field names","coordinate-field-hint":"Rule node tries to retrieve the specified fields from the message. If they are not present, it will look them up in the metadata.","presence-monitoring-strategy":"Presence monitoring strategy","presence-monitoring-strategy-on-first-message":"On first message","presence-monitoring-strategy-on-each-message":"On each message","presence-monitoring-strategy-on-first-message-hint":"Reports presence status 'Inside' or 'Outside' on the first message after the configured minimal duration has passed since previous presence status 'Entered' or 'Left' update.","presence-monitoring-strategy-on-each-message-hint":"Reports presence status 'Inside' or 'Outside' on each message after presence status 'Entered' or 'Left' update.","fetch-credentials-to":"Fetch credentials to","add-originator-attributes-to":"Add originator attributes to","originator-attributes":"Originator attributes","fetch-latest-telemetry-with-timestamp":"Fetch latest telemetry with timestamp","fetch-latest-telemetry-with-timestamp-tooltip":'If selected, latest telemetry values will be added to the outbound metadata with timestamp, e.g: "{{latestTsKeyName}}": "{"ts":1574329385897, "value":42}"',"tell-failure":"Tell failure if any of the attributes are missing","tell-failure-tooltip":'If at least one selected key doesn\'t exist the outbound message will report "Failure".',"created-time":"Created time","chip-help":"Press 'Enter' to complete {{inputName}} input. \nPress 'Backspace' to delete {{inputName}}. \nMultiple values supported.",detail:"detail","field-name":"field name","device-profile":"device profile","entity-type":"entity type","message-type":"message type","timeseries-key":"time series key",type:"Type","first-name":"First name","last-name":"Last name",label:"Label","originator-fields-mapping":"Originator fields mapping","add-mapped-originator-fields-to":"Add mapped originator fields to",fields:"Fields","skip-empty-fields":"Skip empty fields","skip-empty-fields-tooltip":"Fields with empty values will not be added to the output message/output metadata.","fetch-interval":"Fetch interval","fetch-strategy":"Fetch strategy","fetch-timeseries-from-to":"Fetch time series from {{startInterval}} {{startIntervalTimeUnit}} ago to {{endInterval}} {{endIntervalTimeUnit}} ago.","fetch-timeseries-from-to-invalid":'Fetch time series invalid ("Interval start" should be less than "Interval end").',"use-metadata-dynamic-interval-tooltip":"If selected, the rule node will use dynamic interval start and end based on the message and metadata patterns.","all-mode-hint":'If selected fetch mode "All" rule node will retrieve telemetry from the fetch interval with configurable query parameters.',"first-mode-hint":'If selected fetch mode "First" rule node will retrieve the closest telemetry to the fetch interval\'s start.',"last-mode-hint":'If selected fetch mode "Last" rule node will retrieve the closest telemetry to the fetch interval\'s end.',ascending:"Ascending",descending:"Descending",min:"Min",max:"Max",average:"Average",sum:"Sum",count:"Count",none:"None","last-level-relation-tooltip":"If selected, the rule node will search related entities only on the level set in the max relation level.","last-level-device-relation-tooltip":"If selected, the rule node will search related devices only on the level set in the max relation level.","data-to-fetch":"Data to fetch","mapping-of-customers":"Mapping of customer's","map-fields-required":"All mapping fields are required.",attributes:"Attributes","related-device-attributes":"Related device attributes","add-selected-attributes-to":"Add selected attributes to","device-profiles":"Device profiles","mapping-of-tenant":"Mapping of tenant's","add-attribute-key":"Add attribute key","message-template":"Message template","message-template-required":"Message template is required","use-system-slack-settings":"Use system slack settings","slack-api-token":"Slack API token","slack-api-token-required":"Slack API token is required","keys-mapping":"keys mapping","add-key":"Add key",recipients:"Recipients","message-subject-and-content":"Message subject and content","template-rules-hint":"Both input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the message metadata.","originator-customer-desc":"Use customer of incoming message originator as new originator.","originator-tenant-desc":"Use current tenant as new originator.","originator-related-entity-desc":"Use related entity as new originator. Lookup based on configured relation type and direction.","originator-alarm-originator-desc":"Use alarm originator as new originator. Only if incoming message originator is alarm entity.","originator-entity-by-name-pattern-desc":"Use entity fetched from DB as new originator. Lookup based on entity type and specified name pattern.","email-from-template-hint":"Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","recipients-block-main-hint":"Comma-separated address list. All input fields support templatization. Use $[messageKey] to extract value from the message and ${metadataKey} to extract value from the metadata.","forward-msg-default-rule-chain":"Forward message to the originator's default rule chain","forward-msg-default-rule-chain-tooltip":"If enabled, message will be forwarded to the originator's default rule chain, or rule chain from configuration, if originator has no default rule chain defined in the entity profile.","exclude-zero-deltas":"Exclude zero deltas from outbound message","exclude-zero-deltas-hint":'If enabled, the "{{outputValueKey}}" output key will be added to the outbound message if its value is not zero.',"exclude-zero-deltas-time-difference-hint":'If enabled, the "{{outputValueKey}}" and "{{periodValueKey}}" output keys will be added to the outbound message only if the "{{outputValueKey}}" value is not zero.',"search-direction-from":"From originator to target entity","search-direction-to":"From target entity to originator","del-relation-direction-from":"From originator","del-relation-direction-to":"To originator","target-entity":"Target entity","function-configuration":"Function configuration","function-name":"Function name","function-name-required":"Function name is required.",qualifier:"Qualifier","qualifier-hint":'If the qualifier is not specified, the default qualifier "$LATEST" will be used.',"aws-credentials":"AWS Credentials","connection-timeout":"Connection timeout","connection-timeout-required":"Connection timeout is required.","connection-timeout-min":"Min connection timeout is 0.","connection-timeout-hint":"The amount of time to wait in seconds when initially establishing a connection before giving up and timing out. A value of 0 means infinity, and is not recommended.","request-timeout":"Request timeout","request-timeout-required":"Request timeout is required","request-timeout-min":"Min request timeout is 0","request-timeout-hint":"The amount of time to wait in seconds for the request to complete before giving up and timing out. A value of 0 means infinity, and is not recommended.","tell-failure-aws-lambda":"Tell Failure if AWS Lambda function execution raises exception","tell-failure-aws-lambda-hint":"Rule node forces failure of message processing if AWS Lambda function execution raises exception."},"key-val":{key:"Key",value:"Value","see-examples":"See examples.","remove-entry":"Remove entry","remove-mapping-entry":"Remove mapping entry","add-mapping-entry":"Add mapping","add-entry":"Add entry","copy-key-values-from":"Copy key-values from","delete-key-values":"Delete key-values","delete-key-values-from":"Delete key-values from","at-least-one-key-error":"At least one key should be selected.","unique-key-value-pair-error":"'{{keyText}}' must be different from the '{{valText}}'!"},"mail-body-type":{"plain-text":"Plain text",html:"HTML",dynamic:"Dynamic","use-body-type-template":"Use body type template","plain-text-description":"Simple, unformatted text with no special styling or formating.","html-text-description":"Allows you to use HTML tags for formatting, links and images in your mai body.","dynamic-text-description":"Allows to use Plain Text or HTML body type dynamically based on templatization feature.","after-template-evaluation-hint":"After template evaluation value should be true for HTML, and false for Plain text."}}},!0)}(e)}}e("RuleNodeCoreConfigModule",Jr),Jr.ɵfac=t.ɵɵngDeclareFactory({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jr,deps:[{token:X.TranslateService}],target:t.ɵɵFactoryTarget.NgModule}),Jr.ɵmod=t.ɵɵngDeclareNgModule({minVersion:"14.0.0",version:"15.2.10",ngImport:t,type:Jr,declarations:[ut],imports:[J,E],exports:[Yn,Ar,lr,Cr,zr,$r,ut]}),Jr.ɵinj=t.ɵɵngDeclareInjector({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jr,imports:[J,E,Yn,Ar,lr,Cr,zr,$r]}),t.ɵɵngDeclareClassMetadata({minVersion:"12.0.0",version:"15.2.10",ngImport:t,type:Jr,decorators:[{type:d,args:[{declarations:[ut],imports:[J,E],exports:[Yn,Ar,lr,Cr,zr,$r,ut]}]}],ctorParameters:function(){return[{type:X.TranslateService}]}})}}}));//# sourceMappingURL=rulenode-core-config.js.map From 83aff21277bdff9329f2eda2a187873a25be81c3 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 9 Sep 2024 10:55:03 +0300 Subject: [PATCH 35/80] EdgeEventSourcingListener - return in case errors during processing ASSIGNED_TO_EDGE rule chain event --- .../server/service/edge/EdgeEventSourcingListener.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java index 3134a9d0dc..17ceb17ed1 100644 --- a/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java +++ b/application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java @@ -140,10 +140,12 @@ public class EdgeEventSourcingListener { try { Edge edge = JacksonUtil.fromString(event.getBody(), Edge.class); if (edge != null && new RuleChainId(event.getEntityId().getId()).equals(edge.getRootRuleChainId())) { - log.trace("skipping ASSIGNED_TO_EDGE event of RULE_CHAIN entity in case Edge Root Rule Chain: {}", event); + log.trace("[{}] skipping ASSIGNED_TO_EDGE event of RULE_CHAIN entity in case Edge Root Rule Chain: {}", event.getTenantId(), event); return; } - } catch (Exception ignored) {} + } catch (Exception ignored) { + return; + } } log.trace("[{}] ActionEntityEvent called: {}", event.getTenantId(), event); tbClusterService.sendNotificationMsgToEdge(event.getTenantId(), event.getEdgeId(), event.getEntityId(), From 084c7566eed6aa62240a5b3f30ec64c4196822e9 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 9 Sep 2024 11:57:36 +0300 Subject: [PATCH 36/80] UI: Fixed click action for water level symbol --- .../scada_symbols/left-analog-water-level-meter.svg | 12 ++++++++---- .../scada_symbols/right-analog-water-level-meter.svg | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg b/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg index ae02548602..e242edfc11 100644 --- a/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg @@ -1,5 +1,4 @@ - -{ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="200" fill="none" version="1.1" viewBox="0 0 200 200"><tb:metadata xmlns=""><![CDATA[{ "title": "Left analog water level meter", "description": "Left analog water level meter", "searchTags": [ @@ -49,7 +48,11 @@ { "tag": "pointer", "stateRenderFunction": "var valueSet = element.remember('valueSet');\nif (!valueSet) {\n element.remember('valueSet', true);\n element.transform({\n rotate: 0\n });\n}\n\nvar value = ctx.values.value;\nvar fullValue = ctx.values.fullValue;\n\nvar degrees = Math.max(0, Math.min(1, value/fullValue))*179.99;\nvar rotate = element.remember('rotate');\nif (degrees !== rotate) {\n element.remember('rotate', degrees);\n ctx.api.animate(element, 1000).ease('-').transform({rotate: degrees});\n}", - "actions": null + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'displayClick');" + } + } } ], "behavior": [ @@ -610,7 +613,8 @@ "step": null } ] -} +}]]> + Water diff --git a/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg b/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg index 8658a6dc3e..e75949e374 100644 --- a/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg @@ -1,5 +1,4 @@ - -{ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:tb="https://thingsboard.io/svg" width="200" height="200" fill="none" version="1.1" viewBox="0 0 200 200"><tb:metadata xmlns=""><![CDATA[{ "title": "Rigth analog water level meter", "description": "Right analog water level meter", "searchTags": [ @@ -49,7 +48,11 @@ { "tag": "pointer", "stateRenderFunction": "var valueSet = element.remember('valueSet');\nif (!valueSet) {\n element.remember('valueSet', true);\n element.transform({\n rotate: 0\n });\n}\n\nvar value = ctx.values.value;\nvar fullValue = ctx.values.fullValue;\n\nvar degrees = Math.max(0, Math.min(1, value/fullValue))*179.99;\nvar rotate = element.remember('rotate');\nif (degrees !== rotate) {\n element.remember('rotate', degrees);\n ctx.api.animate(element, 1000).ease('-').transform({rotate: degrees});\n}", - "actions": null + "actions": { + "click": { + "actionFunction": "ctx.api.callAction(event, 'displayClick');" + } + } } ], "behavior": [ @@ -610,7 +613,8 @@ "step": null } ] -} +}]]> + Water From ab2fb38e050f479ac4b8b00cca4825c31ba62f8c Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 9 Sep 2024 13:41:40 +0300 Subject: [PATCH 37/80] RuleChainEdgeTest - added testUpdateRootRuleChain --- .../server/edge/AbstractEdgeTest.java | 18 +++++++++--------- .../server/edge/RuleChainEdgeTest.java | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java index b3a1dd790e..34f7da02e6 100644 --- a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java @@ -163,15 +163,10 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { } private RuleChainId getEdgeRootRuleChainId() throws Exception { - List edgeRuleChains = doGetTypedWithPageLink("/api/edge/" + edge.getUuidId() + "/ruleChains?", - new TypeReference>() { - }, new PageLink(100)).getData(); - for (RuleChain edgeRuleChain : edgeRuleChains) { - if (edgeRuleChain.isRoot()) { - return edgeRuleChain.getId(); - } - } - throw new RuntimeException("Root rule chain not found"); + return doGetTypedWithPageLink("/api/ruleChains?type={type}&", new TypeReference>() {}, + new PageLink(100, 0, "Edge Root Rule Chain"), + "EDGE") + .getData().get(0).getId(); } @After @@ -196,6 +191,11 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { Asset savedAsset = saveAsset("Edge Asset 1"); + RuleChainId rootRuleChainId = getEdgeRootRuleChainId(); + RuleChainMetaData rootRuleChainMetadata = doGet("/api/ruleChain/" + rootRuleChainId.getId().toString() + "/metadata", RuleChainMetaData.class); + rootRuleChainMetadata.getNodes().forEach(n -> n.setDebugMode(true)); + doPost("/api/ruleChain/metadata", rootRuleChainMetadata, RuleChainMetaData.class); + edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class); doPost("/api/edge/" + edge.getUuidId() diff --git a/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java index c694df84f8..6dafeefa80 100644 --- a/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java @@ -185,6 +185,21 @@ public class RuleChainEdgeTest extends AbstractEdgeTest { return doPost("/api/ruleChain/metadata", ruleChainMetaData, RuleChainMetaData.class); } + @Test + public void testUpdateRootRuleChain() throws Exception { + RuleChainMetaData rootRuleChainMetadata = doGet("/api/ruleChain/" + edge.getRootRuleChainId().getId().toString() + "/metadata", RuleChainMetaData.class); + + rootRuleChainMetadata.getNodes().forEach(n -> n.setDebugMode(true)); + edgeImitator.expectMessageAmount(2); + doPost("/api/ruleChain/metadata", rootRuleChainMetadata, RuleChainMetaData.class); + Assert.assertTrue(edgeImitator.waitForMessages()); + + Optional ruleChainUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainUpdateMsg.class); + Assert.assertTrue(ruleChainUpdateMsgOpt.isPresent()); + Optional ruleChainMetadataUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainMetadataUpdateMsg.class); + Assert.assertTrue(ruleChainMetadataUpdateMsgOpt.isPresent()); + } + @Test public void testSetRootRuleChain() throws Exception { // create rule chain From 6098f19dc23163185ffb7a10e72d942cb87e6e53 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 9 Sep 2024 13:51:49 +0300 Subject: [PATCH 38/80] Refactoring to remove duplicates --- .../thingsboard/server/edge/AbstractEdgeTest.java | 15 +++++++++++---- .../server/edge/RuleChainEdgeTest.java | 5 +---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java index 34f7da02e6..5484c29305 100644 --- a/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/AbstractEdgeTest.java @@ -103,6 +103,7 @@ import org.thingsboard.server.gen.edge.v1.UserUpdateMsg; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.Random; import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -124,6 +125,8 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { protected EdgeImitator edgeImitator; protected Edge edge; + private Random random = new Random(); + @Autowired protected EdgeEventService edgeEventService; @@ -191,10 +194,7 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { Asset savedAsset = saveAsset("Edge Asset 1"); - RuleChainId rootRuleChainId = getEdgeRootRuleChainId(); - RuleChainMetaData rootRuleChainMetadata = doGet("/api/ruleChain/" + rootRuleChainId.getId().toString() + "/metadata", RuleChainMetaData.class); - rootRuleChainMetadata.getNodes().forEach(n -> n.setDebugMode(true)); - doPost("/api/ruleChain/metadata", rootRuleChainMetadata, RuleChainMetaData.class); + updateRootRuleChainMetadata(); edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class); @@ -207,6 +207,13 @@ abstract public class AbstractEdgeTest extends AbstractControllerTest { TimeUnit.MILLISECONDS.sleep(1000); } + protected void updateRootRuleChainMetadata() throws Exception { + RuleChainId rootRuleChainId = getEdgeRootRuleChainId(); + RuleChainMetaData rootRuleChainMetadata = doGet("/api/ruleChain/" + rootRuleChainId.getId().toString() + "/metadata", RuleChainMetaData.class); + rootRuleChainMetadata.getNodes().forEach(n -> n.setDebugMode(random.nextBoolean())); + doPost("/api/ruleChain/metadata", rootRuleChainMetadata, RuleChainMetaData.class); + } + protected void extendDeviceProfileData(DeviceProfile deviceProfile) { DeviceProfileData profileData = deviceProfile.getProfileData(); List alarms = new ArrayList<>(); diff --git a/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java index 6dafeefa80..eaf4468156 100644 --- a/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/RuleChainEdgeTest.java @@ -187,11 +187,8 @@ public class RuleChainEdgeTest extends AbstractEdgeTest { @Test public void testUpdateRootRuleChain() throws Exception { - RuleChainMetaData rootRuleChainMetadata = doGet("/api/ruleChain/" + edge.getRootRuleChainId().getId().toString() + "/metadata", RuleChainMetaData.class); - - rootRuleChainMetadata.getNodes().forEach(n -> n.setDebugMode(true)); edgeImitator.expectMessageAmount(2); - doPost("/api/ruleChain/metadata", rootRuleChainMetadata, RuleChainMetaData.class); + updateRootRuleChainMetadata(); Assert.assertTrue(edgeImitator.waitForMessages()); Optional ruleChainUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainUpdateMsg.class); From 28953b4c5b462eba3f8bda235775db041b7e0c79 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Mon, 9 Sep 2024 14:40:23 +0300 Subject: [PATCH 39/80] UI: update scada bundle and add images --- .../widget_bundles/scada_fluid_system.json | 74 +++++++++++++++++++ .../system/widget_bundles/scada_symbols.json | 2 +- .../scada_water_system_symbols.json | 74 ------------------- .../system/widget_types/scada_symbol.json | 2 +- 4 files changed, 76 insertions(+), 76 deletions(-) create mode 100644 application/src/main/data/json/system/widget_bundles/scada_fluid_system.json delete mode 100644 application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json diff --git a/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json b/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json new file mode 100644 index 0000000000..405185ae21 --- /dev/null +++ b/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json @@ -0,0 +1,74 @@ +{ + "widgetsBundle": { + "alias": "scada_fluid_system", + "title": "SCADA fluid system", + "image": "tb-image:c2NhZGFfZmx1aWRfc3lzdGVtX2J1bmRsZV9pbWFnZS5wbmc=:IlNDQURBIGZsdWlkIHN5c3RlbSIgc3lzdGVtIGJ1bmRsZSBpbWFnZQ==:SU1BR0U=;data:image/png;base64,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", + "scada": true, + "description": "Bundle with SCADA symbols for fluid system", + "order": 9300, + "name": "SCADA fluid system" + }, + "widgetTypeFqns": [ + "horizontal_pipe", + "long_horizontal_pipe", + "vertical_pipe", + "long_vertical_pipe", + "left_bottom_elbow_pipe", + "bottom_right_elbow_pipe", + "top_right_elbow_pipe", + "left_top_elbow_pipe", + "cross_pipe", + "left_tee_pipe", + "bottom_tee_pipe", + "right_tee_pipe", + "top_tee_pipe", + "right_elbow_drain_pipe", + "left_elbow_drain_pipe", + "left_drain_pipe", + "right_drain_pipe", + "short_left_drain_pipe", + "short_right_drain_pipe", + "top_flow_meter", + "right_flow_meter", + "bottom_flow_meter", + "left_flow_meter", + "horizontal_inline_flow_meter", + "vertical_inline_flow_meter", + "left_analog_water_level_meter", + "right_analog_water_level_meter", + "leak_sensor", + "centrifugal_pump", + "small_right_motor_pump", + "small_left_motor_pump", + "right_motor_pump", + "left_motor_pump", + "right_heat_pump", + "left_heat_pump", + "short_bottom_filter", + "long_bottom_filter", + "short_top_filter", + "long_top_filter", + "stand_filter", + "horizontal_wheel_valve", + "vertical_wheel_valve", + "horizontal_ball_valve", + "vertical_ball_valve", + "water_stop", + "vertical_tank", + "stand_vertical_tank", + "cylindrical_tank", + "stand_cylindrical_tank", + "vertical_short_tank", + "stand_vertical_short_tank", + "large_cylindrical_tank", + "large_stand_cylindrical_tank", + "large_vertical_tank", + "large_stand_vertical_tank", + "horizontal_tank", + "stand_horizontal_tank", + "spherical_tank", + "small_spherical_tank", + "elevated_tank", + "pool" + ] +} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_bundles/scada_symbols.json b/application/src/main/data/json/system/widget_bundles/scada_symbols.json index f1fbfbc297..803a3a9126 100644 --- a/application/src/main/data/json/system/widget_bundles/scada_symbols.json +++ b/application/src/main/data/json/system/widget_bundles/scada_symbols.json @@ -3,7 +3,7 @@ "alias": "scada_symbols", "title": "SCADA symbols", "scada": true, - "image": null, + "image": "tb-image:c2NhZGFfc3ltYm9sc19zeXN0ZW1fYnVuZGxlX2ltYWdlLnBuZw==:IlNDQURBIHN5bWJvbHMiIHN5c3RlbSBidW5kbGUgaW1hZ2U=:SU1BR0U=;data:image/png;base64,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", "description": "Bundle with SCADA symbols", "order": 9200, "name": "SCADA symbols" diff --git a/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json b/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json deleted file mode 100644 index 22575e0697..0000000000 --- a/application/src/main/data/json/system/widget_bundles/scada_water_system_symbols.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "widgetsBundle": { - "alias": "scada_water_system_symbols", - "title": "SCADA water system symbols", - "scada": true, - "image": null, - "description": "Bundle with SCADA symbols for water system", - "order": 9300, - "name": "SCADA water system symbols" - }, - "widgetTypeFqns": [ - "horizontal_pipe", - "long_horizontal_pipe", - "vertical_pipe", - "long_vertical_pipe", - "left_bottom_elbow_pipe", - "bottom_right_elbow_pipe", - "top_right_elbow_pipe", - "left_top_elbow_pipe", - "cross_pipe", - "left_tee_pipe", - "bottom_tee_pipe", - "right_tee_pipe", - "top_tee_pipe", - "right_elbow_drain_pipe", - "left_elbow_drain_pipe", - "left_drain_pipe", - "right_drain_pipe", - "short_left_drain_pipe", - "short_right_drain_pipe", - "top_flow_meter", - "right_flow_meter", - "bottom_flow_meter", - "left_flow_meter", - "horizontal_inline_flow_meter", - "vertical_inline_flow_meter", - "left_analog_water_level_meter", - "right_analog_water_level_meter", - "leak_sensor", - "centrifugal_pump", - "small_right_motor_pump", - "small_left_motor_pump", - "right_motor_pump", - "left_motor_pump", - "right_heat_pump", - "left_heat_pump", - "short_bottom_filter", - "long_bottom_filter", - "short_top_filter", - "long_top_filter", - "stand_filter", - "horizontal_wheel_valve", - "vertical_wheel_valve", - "horizontal_ball_valve", - "vertical_ball_valve", - "water_stop", - "vertical_tank", - "stand_vertical_tank", - "cylindrical_tank", - "stand_cylindrical_tank", - "vertical_short_tank", - "stand_vertical_short_tank", - "large_cylindrical_tank", - "large_stand_cylindrical_tank", - "large_vertical_tank", - "large_stand_vertical_tank", - "horizontal_tank", - "stand_horizontal_tank", - "spherical_tank", - "small_spherical_tank", - "elevated_tank", - "pool" - ] -} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_types/scada_symbol.json b/application/src/main/data/json/system/widget_types/scada_symbol.json index 15c12e1b81..61ef5bb529 100644 --- a/application/src/main/data/json/system/widget_types/scada_symbol.json +++ b/application/src/main/data/json/system/widget_types/scada_symbol.json @@ -3,7 +3,7 @@ "name": "SCADA symbol", "deprecated": false, "scada": true, - "image": null, + "image": "tb-image:bmV3X3NjYWRhX3N5bWJvbHNfc3lzdGVtX3dpZGdldF9pbWFnZS5wbmc=:Ik5ldyBTQ0FEQSBzeW1ib2wiIHN5c3RlbSB3aWRnZXQgaW1hZ2U=:SU1BR0U=;data:image/png;base64,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", "description": "", "descriptor": { "type": "rpc", From c4441eba72c05c683bca9e1516efde3b998312b2 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 9 Sep 2024 15:30:57 +0300 Subject: [PATCH 40/80] changed approach to abstract class for mapping --- ...ay-connector-version-processor.abstract.ts | 36 ++++++++ .../mqtt-version-processor.abstract.ts | 76 +++++++++++++++++ .../mqtt-basic-config.abstract.ts | 13 ++- .../mqtt-basic-config.component.ts | 8 +- .../mqtt-legacy-basic-config.component.ts | 14 ++-- .../dialog/add-connector-dialog.component.ts | 11 ++- .../gateway/gateway-connectors.component.ts | 8 +- .../lib/gateway/gateway-widget.models.ts | 19 ++--- .../gateway-connector-version-mapping.util.ts | 46 ++-------- .../utils/mqtt-version-mapping.util.ts | 84 +++---------------- .../connector-default-configs/mqtt.json | 2 +- 11 files changed, 168 insertions(+), 149 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts new file mode 100644 index 0000000000..1a1c4f05bc --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts @@ -0,0 +1,36 @@ +import { GatewayConnector } from '@home/components/widget/lib/gateway/gateway-widget.models'; + +export abstract class GatewayConnectorVersionProcessor { + gatewayVersion: number; + configVersion: number; + + protected constructor(protected gatewayVersionStr: string, protected connector: GatewayConnector) { + this.gatewayVersion = this.parseVersion(this.gatewayVersionStr); + this.configVersion = this.parseVersion(connector.configVersion); + } + + getProcessedByVersion(): BasicConfig { + if (this.isVersionUpdateNeeded()) { + return this.configVersion > this.gatewayVersion + ? this.getDowngradedVersion() + : this.getUpgradedVersion(); + } + + return this.connector.configurationJson as unknown as BasicConfig; + } + + private isVersionUpdateNeeded(): boolean { + if (!this.gatewayVersion || !this.configVersion) { + return false; + } + + return this.configVersion !== this.gatewayVersion; + } + + private parseVersion(version: string): number { + return Number(version?.replace(/\./g, '')); + } + + abstract getDowngradedVersion(): BasicConfig; + abstract getUpgradedVersion(): BasicConfig; +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts new file mode 100644 index 0000000000..2a7bea0e1b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts @@ -0,0 +1,76 @@ +import { + GatewayConnectorVersionProcessor +} from '@home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract'; +import { + GatewayConnector, + MQTTBasicConfig, MQTTBasicConfig_v3_5_2, + MQTTLegacyBasicConfig, + RequestMappingData, + RequestType, +} from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { isEqual } from '@core/utils'; +import { MqttVersionMappingUtil } from '@home/components/widget/lib/gateway/utils/mqtt-version-mapping.util'; + +export class MqttVersionProcessor extends GatewayConnectorVersionProcessor { + private readonly mqttRequestTypeKeys = Object.values(RequestType); + + constructor( + protected gatewayVersionStr: string, + protected connector: GatewayConnector + ) { + super(gatewayVersionStr, connector); + } + getUpgradedVersion(): MQTTBasicConfig { + const { + connectRequests, + disconnectRequests, + attributeRequests, + attributeUpdates, + serverSideRpc + } = this.connector.configurationJson as MQTTLegacyBasicConfig; + let configurationJson = { + ...this.connector.configurationJson, + requestsMapping: MqttVersionMappingUtil.mapRequestsToUpgradedVersion({ + connectRequests, + disconnectRequests, + attributeRequests, + attributeUpdates, + serverSideRpc + }), + mapping: MqttVersionMappingUtil.mapMappingToUpgradedVersion((this.connector.configurationJson as MQTTLegacyBasicConfig).mapping), + }; + + this.mqttRequestTypeKeys.forEach((key: RequestType) => { + const { [key]: removedKey, ...rest } = configurationJson as MQTTLegacyBasicConfig; + configurationJson = { ...rest } as any; + }); + + this.cleanUpConfigJson(configurationJson as MQTTBasicConfig_v3_5_2); + + return configurationJson as MQTTBasicConfig; + } + + getDowngradedVersion(): MQTTLegacyBasicConfig { + const { requestsMapping, mapping, ...restConfig } = this.connector.configurationJson as MQTTBasicConfig_v3_5_2; + + const updatedRequestsMapping = + MqttVersionMappingUtil.mapRequestsToDowngradedVersion(requestsMapping as Record); + const updatedMapping = MqttVersionMappingUtil.mapMappingToDowngradedVersion(mapping); + + return { + ...restConfig, + ...updatedRequestsMapping, + mapping: updatedMapping, + }; + } + + private cleanUpConfigJson(configurationJson: MQTTBasicConfig_v3_5_2): void { + if (isEqual(configurationJson.requestsMapping, {})) { + delete configurationJson.requestsMapping; + } + + if (isEqual(configurationJson.mapping, [])) { + delete configurationJson.mapping; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts index 12529d942f..072d8ba834 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts @@ -17,24 +17,23 @@ import { ControlValueAccessor, FormBuilder, FormGroup, ValidationErrors, Validator } from '@angular/forms'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { isObject } from 'lodash'; import { MappingType, MQTTBasicConfig, - MQTTLegacyBasicConfig, RequestMappingData, RequestMappingValue, RequestType } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { Directive, OnDestroy } from '@angular/core'; +import { isObject } from '@core/utils'; @Directive() -export abstract class AbstractMqttBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy { +export abstract class AbstractMqttBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy { basicFormGroup: FormGroup; mappingTypes = MappingType; private destroy$ = new Subject(); - private onChange: (value: MQTTBasicConfig | MQTTLegacyBasicConfig) => void; + private onChange: (value: BasicConfig) => void; private onTouched: () => void; constructor(protected fb: FormBuilder) { @@ -58,7 +57,7 @@ export abstract class AbstractMqttBasicConfigComponent implements ControlValueAc this.destroy$.complete(); } - registerOnChange(fn: (value: MQTTBasicConfig | MQTTLegacyBasicConfig) => void): void { + registerOnChange(fn: (value: BasicConfig) => void): void { this.onChange = fn; } @@ -102,6 +101,6 @@ export abstract class AbstractMqttBasicConfigComponent implements ControlValueAc }); } - abstract writeValue(basicConfig: MQTTBasicConfig | MQTTLegacyBasicConfig): void; - protected abstract getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig | MQTTLegacyBasicConfig; + abstract writeValue(basicConfig: BasicConfig): void; + protected abstract getMappedMQTTConfig(basicConfig: MQTTBasicConfig): BasicConfig; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts index c4ebadb03d..e2c9918179 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts @@ -17,7 +17,7 @@ import { Component, forwardRef, Input, TemplateRef, ChangeDetectionStrategy } from '@angular/core'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms'; import { - MQTTBasicConfig, + MQTTBasicConfig_v3_5_2, RequestMappingData, RequestMappingValue, RequestType @@ -68,12 +68,12 @@ import { MappingTableComponent, ], }) -export class MqttBasicConfigComponent extends AbstractMqttBasicConfigComponent { +export class MqttBasicConfigComponent extends AbstractMqttBasicConfigComponent { @Input() generalTabContent: TemplateRef; - writeValue(basicConfig: MQTTBasicConfig): void { + writeValue(basicConfig: MQTTBasicConfig_v3_5_2): void { const { broker, mapping = [], requestsMapping } = basicConfig; const editedBase = { workers: broker && (broker.maxNumberOfWorkers || broker.maxMessageNumberPerWorker) ? { @@ -88,7 +88,7 @@ export class MqttBasicConfigComponent extends AbstractMqttBasicConfigComponent { this.basicFormGroup.setValue(editedBase, {emitEvent: false}); } - protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig { + protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig_v3_5_2): MQTTBasicConfig_v3_5_2 { let { broker, workers, mapping, requestsMapping } = basicConfig || {}; if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts index 92e4e5b4b5..2ca5eba000 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts @@ -17,7 +17,7 @@ import { Component, forwardRef, Input, TemplateRef, ChangeDetectionStrategy } from '@angular/core'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms'; import { - MQTTBasicConfig, + MQTTBasicConfig_v3_5_2, MQTTLegacyBasicConfig, RequestMappingData, RequestMappingValue, @@ -70,7 +70,7 @@ import { MappingTableComponent, ], }) -export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigComponent { +export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigComponent { @Input() generalTabContent: TemplateRef; @@ -85,7 +85,7 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo attributeUpdates = [], serverSideRpc = [] } = basicConfig; - const updatedRequestMapping = MqttVersionMappingUtil.mapRequestsToNewestVersion({ + const updatedRequestMapping = MqttVersionMappingUtil.mapRequestsToUpgradedVersion({ connectRequests, disconnectRequests, attributeRequests, @@ -97,7 +97,7 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo maxNumberOfWorkers: broker.maxNumberOfWorkers, maxMessageNumberPerWorker: broker.maxMessageNumberPerWorker, } : {}, - mapping: MqttVersionMappingUtil.mapMappingToNewestVersion(mapping) || [], + mapping: MqttVersionMappingUtil.mapMappingToUpgradedVersion(mapping) || [], broker: broker || {}, requestsMapping: this.getRequestDataArray(updatedRequestMapping), }; @@ -105,7 +105,7 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo this.basicFormGroup.setValue(editedBase, {emitEvent: false}); } - protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTLegacyBasicConfig { + protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig_v3_5_2): MQTTLegacyBasicConfig { let { broker, workers, mapping, requestsMapping } = basicConfig || {}; if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) { @@ -121,8 +121,8 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo return { broker, - mapping: MqttVersionMappingUtil.mapMappingToLegacyVersion(mapping), - ...(MqttVersionMappingUtil.mapRequestsToLegacyVersion(requestsMapping as Record)) + mapping: MqttVersionMappingUtil.mapMappingToDowngradedVersion(mapping), + ...(MqttVersionMappingUtil.mapRequestsToDowngradedVersion(requestsMapping as Record)) }; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts index d79a1d3fec..0168cf86af 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts @@ -97,8 +97,15 @@ export class AddConnectorDialogComponent this.submitted = true; const value = this.connectorForm.getRawValue(); if (value.useDefaults) { - this.getDefaultConfig(value.type).subscribe(({current, legacy, ...defaultConfig}: GatewayVersionedDefaultConfig) => { - value.configurationJson = (this.data.gatewayVersion ? current : legacy) ?? defaultConfig; + this.getDefaultConfig(value.type).subscribe((defaultConfig: GatewayVersionedDefaultConfig) => { + const gatewayVersion = this.data.gatewayVersion; + if (gatewayVersion) { + value.configVersion = gatewayVersion; + } + value.configurationJson = (gatewayVersion + ? defaultConfig[this.data.gatewayVersion] + : defaultConfig.legacy) + ?? defaultConfig; if (this.connectorForm.valid) { this.dialogRef.close(value); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index d7d412f6da..96e15a110f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -65,7 +65,9 @@ import { AddConnectorDialogComponent } from '@home/components/widget/lib/gateway import { debounceTime, filter, switchMap, take, takeUntil, tap } from 'rxjs/operators'; import { ErrorStateMatcher } from '@angular/material/core'; import { PageData } from '@shared/models/page/page-data'; -import { GatewayConnectorVersionMappingUtil } from './utils/gateway-connector-version-mapping.util'; +import { + GatewayConnectorVersionMappingUtil +} from '@home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util'; export class ForceErrorStateMatcher implements ErrorStateMatcher { isErrorState(control: FormControl | null): boolean { @@ -247,7 +249,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie value.ts = Date.now(); - return GatewayConnectorVersionMappingUtil.getMappedByVersion(value, this.gatewayVersion); + return value; } private updateData(reload: boolean = false): void { @@ -741,7 +743,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie ...connector, }; - connectorState.basicConfig = connectorState.configurationJson; + connectorState.basicConfig = GatewayConnectorVersionMappingUtil.getConfig(connectorState, this.gatewayVersion); this.initialConnector = connectorState; this.updateConnector(connectorState); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 4770eeea23..38040f15d3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -124,21 +124,14 @@ export interface GatewayConnectorBase { configVersion?: string; } -export type GatewayConnector = CurrentGatewayConnector | LegacyGatewayConnector; - -export interface CurrentGatewayConnector extends GatewayConnectorBase { +export interface GatewayConnector extends GatewayConnectorBase { configurationJson: ConnectorBaseConfig; basicConfig?: ConnectorBaseConfig; } -export interface LegacyGatewayConnector extends GatewayConnectorBase { - configurationJson: ConnectorLegacyBaseConfig; - basicConfig?: ConnectorLegacyBaseConfig; -} - export interface GatewayVersionedDefaultConfig { - legacy: LegacyGatewayConnector; - current: GatewayConnector; + legacy: GatewayConnector; + '3.5.1': GatewayConnector; } export interface DataMapping { @@ -201,8 +194,6 @@ export type ConnectorMappingFormValue = DeviceConnectorMapping | RequestMappingF export type ConnectorBaseConfig = ConnectorBaseInfo | MQTTBasicConfig | OPCBasicConfig | ModbusBasicConfig; -export type ConnectorLegacyBaseConfig = ConnectorBaseInfo | MQTTLegacyBasicConfig; - export interface ConnectorBaseInfo { name: string; id: string; @@ -210,7 +201,9 @@ export interface ConnectorBaseInfo { logLevel: GatewayLogLevel; } -export interface MQTTBasicConfig { +export type MQTTBasicConfig = MQTTBasicConfig_v3_5_2 | MQTTLegacyBasicConfig; + +export interface MQTTBasicConfig_v3_5_2 { mapping: ConverterConnectorMapping[]; requestsMapping: Record | RequestMappingData[] | RequestMappingValue[]; broker: BrokerConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts index 6a48b5e64b..ab9e393fee 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts @@ -15,52 +15,20 @@ /// import { + ConnectorBaseConfig, ConnectorType, GatewayConnector, - LegacyGatewayConnector, } from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { MqttVersionMappingUtil } from './mqtt-version-mapping.util'; +import { MqttVersionProcessor } from '@home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract'; -export class GatewayConnectorVersionMappingUtil { +export abstract class GatewayConnectorVersionMappingUtil { - static getMappedByVersion(connector: GatewayConnector, gatewayVersion: string): GatewayConnector { - switch (connector.type) { + static getConfig(connector: GatewayConnector, gatewayVersion: string): ConnectorBaseConfig { + switch(connector.type) { case ConnectorType.MQTT: - return this.getMappedMQTTByVersion(connector, gatewayVersion); + return new MqttVersionProcessor(gatewayVersion, connector).getProcessedByVersion(); default: - return connector; + return connector.configurationJson as ConnectorBaseConfig; } } - - private static getMappedMQTTByVersion( - connector: GatewayConnector | LegacyGatewayConnector, - gatewayVersion: string - ): GatewayConnector | LegacyGatewayConnector { - if (this.isVersionUpdateNeeded(gatewayVersion, connector.configVersion)) { - return this.isGatewayOutdated(gatewayVersion, connector.configVersion) - ? MqttVersionMappingUtil.getLegacyVersion(connector) - : MqttVersionMappingUtil.getNewestVersion(connector); - } - return connector; - } - - private static isGatewayOutdated(gatewayVersion: string, configVersion: string): boolean { - if (!gatewayVersion || !configVersion) { - return false; - } - - return this.parseVersion(configVersion) > this.parseVersion(gatewayVersion); - } - - private static isVersionUpdateNeeded(configVersion: string, gatewayVersion: string): boolean { - if (!gatewayVersion || !configVersion) { - return false; - } - - return this.parseVersion(configVersion) !== this.parseVersion(gatewayVersion); - } - - private static parseVersion(version: string): number { - return Number(version?.replace(/\./g, '')); - } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts index e32d020730..ffd517c3e9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts @@ -14,21 +14,16 @@ /// limitations under the License. /// -import { deleteNullProperties, isEqual } from '@core/utils'; +import { deleteNullProperties } from '@core/utils'; import { AttributeRequest, ConnectorDeviceInfo, Converter, ConverterConnectorMapping, ConvertorType, - CurrentGatewayConnector, - GatewayConnector, LegacyConverter, LegacyConverterConnectorMapping, - LegacyGatewayConnector, LegacyRequestMappingData, - MQTTBasicConfig, - MQTTLegacyBasicConfig, RequestMappingData, RequestType, ServerSideRpc, @@ -44,56 +39,9 @@ export class MqttVersionMappingUtil { static readonly mqttRequestMappingNewFields = ['attributeNameExpressionSource', 'responseTopicQoS', 'extensionConfig']; - static getNewestVersion(mqttConnector: GatewayConnector): CurrentGatewayConnector { - const { - connectRequests, - disconnectRequests, - attributeRequests, - attributeUpdates, - serverSideRpc - } = mqttConnector.configurationJson as MQTTLegacyBasicConfig; - let configurationJson = { - ...mqttConnector.configurationJson, - requestsMapping: this.mapRequestsToNewestVersion({ - connectRequests, - disconnectRequests, - attributeRequests, - attributeUpdates, - serverSideRpc - }), - mapping: this.mapMappingToNewestVersion((mqttConnector.configurationJson as MQTTLegacyBasicConfig).mapping), - }; - - this.mqttRequestTypeKeys.forEach((key: RequestType) => { - const { [key]: removedKey, ...rest } = configurationJson as MQTTLegacyBasicConfig; - configurationJson = { ...rest } as any; - }); - - this.cleanUpConfigJson(configurationJson as MQTTBasicConfig); - - return { - ...mqttConnector, - configurationJson - } as CurrentGatewayConnector; - } - - static getLegacyVersion(mqttConnector: GatewayConnector): LegacyGatewayConnector { - const { requestsMapping, mapping, ...restConfig } = mqttConnector.configurationJson as MQTTBasicConfig; - - const updatedRequestsMapping = this.mapRequestsToLegacyVersion(requestsMapping as Record); - const updatedMapping = this.mapMappingToLegacyVersion(mapping); - - return { - ...mqttConnector, - configurationJson: { - ...restConfig, - ...updatedRequestsMapping, - mapping: updatedMapping, - }, - } as LegacyGatewayConnector; - } - - static mapMappingToNewestVersion(mapping: LegacyConverterConnectorMapping[] | ConverterConnectorMapping[]): ConverterConnectorMapping[] { + static mapMappingToUpgradedVersion( + mapping: LegacyConverterConnectorMapping[] | ConverterConnectorMapping[] + ): ConverterConnectorMapping[] { return mapping?.map(({ converter, topicFilter, subscriptionQos = 1 }) => { const deviceInfo = converter.deviceInfo ?? this.extractConverterDeviceInfo(converter); @@ -109,7 +57,7 @@ export class MqttVersionMappingUtil { }); } - static mapRequestsToNewestVersion( + static mapRequestsToUpgradedVersion( requestMapping: Record ): Record { @@ -119,7 +67,7 @@ export class MqttVersionMappingUtil { } acc[key] = requestMapping[key].map(value => { - const newValue = this.mapRequestToNewest(value as LegacyRequestMappingData, key); + const newValue = this.mapRequestToUpgradedVersion(value as LegacyRequestMappingData, key); this.cleanUpOldFields(newValue as {}); @@ -130,7 +78,7 @@ export class MqttVersionMappingUtil { }, {}) as Record; } - static mapRequestsToLegacyVersion( + static mapRequestsToDowngradedVersion( requestsMapping: Record ): Record { return this.mqttRequestTypeKeys.reduce((acc, key) => { @@ -161,11 +109,11 @@ export class MqttVersionMappingUtil { }, {}) as Record; } - static mapMappingToLegacyVersion( + static mapMappingToDowngradedVersion( mapping: ConverterConnectorMapping[] ): LegacyConverterConnectorMapping[] { return mapping?.map((converterMapping: ConverterConnectorMapping) => { - const converter = this.mapConverterToLegacy(converterMapping.converter); + const converter = this.mapConverterToDowngradedVersion(converterMapping.converter); this.cleanUpNewFields(converter as {}); @@ -173,7 +121,7 @@ export class MqttVersionMappingUtil { }); } - private static mapConverterToLegacy(converter: Converter): LegacyConverter { + private static mapConverterToDowngradedVersion(converter: Converter): LegacyConverter { const { deviceInfo, ...restConverter } = converter; return converter.type !== ConvertorType.BYTES ? { @@ -216,16 +164,6 @@ export class MqttVersionMappingUtil { return SourceType.CONST; } - private static cleanUpConfigJson(configurationJson: MQTTBasicConfig): void { - if (isEqual(configurationJson.requestsMapping, {})) { - delete configurationJson.requestsMapping; - } - - if (isEqual(configurationJson.mapping, [])) { - delete configurationJson.mapping; - } - } - private static extractConverterDeviceInfo(converter: LegacyConverter): ConnectorDeviceInfo { const deviceNameExpression = converter.deviceNameExpression || converter.deviceNameJsonExpression @@ -250,7 +188,7 @@ export class MqttVersionMappingUtil { } : null; } - private static mapRequestToNewest(value, key: RequestType): RequestMappingData { + private static mapRequestToUpgradedVersion(value, key: RequestType): RequestMappingData { const deviceNameExpression = value.deviceNameJsonExpression || value.deviceNameTopicExpression || null; const deviceProfileExpression = value.deviceTypeTopicExpression || value.deviceTypeJsonExpression || 'default'; const deviceProfileExpressionSource = deviceProfileExpression ? this.getTypeSourceByValue(deviceProfileExpression) : null; diff --git a/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json b/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json index 96ab233ef4..b3ba47215f 100644 --- a/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json +++ b/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json @@ -1,5 +1,5 @@ { - "current": { + "3.5.1": { "broker": { "host": "127.0.0.1", "port": 1883, From 80957f32593f370a2e21268bce867c0fe366cbf2 Mon Sep 17 00:00:00 2001 From: imbeacon Date: Mon, 9 Sep 2024 15:52:55 +0300 Subject: [PATCH 41/80] Changes due to comments --- .../server/dao/asset/AssetProfileServiceImpl.java | 8 ++++---- .../server/dao/device/DeviceProfileServiceImpl.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java index f0d52d312a..7d4d5300f9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java @@ -236,9 +236,9 @@ public class AssetProfileServiceImpl extends CachedVersionedEntityService INCORRECT_TENANT_ID + id); AssetProfile assetProfile = new AssetProfile(); assetProfile.setTenantId(tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java index 9594598a12..09e2be01e0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java @@ -271,9 +271,9 @@ public class DeviceProfileServiceImpl extends CachedVersionedEntityService INCORRECT_TENANT_ID + id); DeviceProfile deviceProfile = new DeviceProfile(); deviceProfile.setTenantId(tenantId); From f97598ee081f0244cf83f16e8fc3da4553c83f90 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 9 Sep 2024 16:17:00 +0300 Subject: [PATCH 42/80] refactoring --- ...ay-connector-version-processor.abstract.ts | 6 +++--- .../mqtt-version-processor.abstract.ts | 19 +++++++++---------- .../mqtt-basic-config.abstract.ts | 2 ++ .../mqtt-basic-config.component.ts | 4 ++-- .../gateway/gateway-connectors.component.ts | 6 +----- .../utils/mqtt-version-mapping.util.ts | 6 +++--- 6 files changed, 20 insertions(+), 23 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts index 1a1c4f05bc..31b8ba8cf8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts @@ -11,9 +11,9 @@ export abstract class GatewayConnectorVersionProcessor { getProcessedByVersion(): BasicConfig { if (this.isVersionUpdateNeeded()) { - return this.configVersion > this.gatewayVersion - ? this.getDowngradedVersion() - : this.getUpgradedVersion(); + return this.configVersion < this.gatewayVersion + ? this.getUpgradedVersion() + : this.getDowngradedVersion(); } return this.connector.configurationJson as unknown as BasicConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts index 2a7bea0e1b..875b238d7e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts @@ -1,15 +1,14 @@ -import { - GatewayConnectorVersionProcessor -} from '@home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract'; +import { isEqual } from '@core/utils'; import { GatewayConnector, - MQTTBasicConfig, MQTTBasicConfig_v3_5_2, + MQTTBasicConfig, + MQTTBasicConfig_v3_5_2, MQTTLegacyBasicConfig, RequestMappingData, RequestType, -} from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { isEqual } from '@core/utils'; -import { MqttVersionMappingUtil } from '@home/components/widget/lib/gateway/utils/mqtt-version-mapping.util'; +} from '../gateway-widget.models'; +import { MqttVersionMappingUtil } from '../utils/mqtt-version-mapping.util'; +import { GatewayConnectorVersionProcessor } from './gateway-connector-version-processor.abstract'; export class MqttVersionProcessor extends GatewayConnectorVersionProcessor { private readonly mqttRequestTypeKeys = Object.values(RequestType); @@ -20,7 +19,7 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor { - const { [key]: removedKey, ...rest } = configurationJson as MQTTLegacyBasicConfig; + const { [key]: removedValue, ...rest } = configurationJson as MQTTLegacyBasicConfig; configurationJson = { ...rest } as any; }); this.cleanUpConfigJson(configurationJson as MQTTBasicConfig_v3_5_2); - return configurationJson as MQTTBasicConfig; + return configurationJson as MQTTBasicConfig_v3_5_2; } getDowngradedVersion(): MQTTLegacyBasicConfig { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts index 072d8ba834..0394604d42 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts @@ -32,7 +32,9 @@ export abstract class AbstractMqttBasicConfigComponent implements C basicFormGroup: FormGroup; mappingTypes = MappingType; + private destroy$ = new Subject(); + private onChange: (value: BasicConfig) => void; private onTouched: () => void; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts index e2c9918179..541866dab8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts @@ -80,8 +80,8 @@ export class MqttBasicConfigComponent extends AbstractMqttBasicConfigComponent), }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index 96e15a110f..b6e2dfc093 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -243,10 +243,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie delete value.class; } - if (this.gatewayVersion && !value.configVersion) { - value.configVersion = this.gatewayVersion; - } - value.ts = Date.now(); return value; @@ -482,7 +478,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie value.configurationJson = {} as ConnectorBaseConfig; } value.basicConfig = value.configurationJson; - this.updateConnector({...value, configVersion: this.gatewayVersion ?? ''}); + this.updateConnector(value); this.generate('basicConfig.broker.clientId'); setTimeout(() => this.saveConnector()); }); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts index ffd517c3e9..23cc03dc4e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/mqtt-version-mapping.util.ts @@ -40,7 +40,7 @@ export class MqttVersionMappingUtil { ['attributeNameExpressionSource', 'responseTopicQoS', 'extensionConfig']; static mapMappingToUpgradedVersion( - mapping: LegacyConverterConnectorMapping[] | ConverterConnectorMapping[] + mapping: LegacyConverterConnectorMapping[] ): ConverterConnectorMapping[] { return mapping?.map(({ converter, topicFilter, subscriptionQos = 1 }) => { const deviceInfo = converter.deviceInfo ?? this.extractConverterDeviceInfo(converter); @@ -54,12 +54,12 @@ export class MqttVersionMappingUtil { this.cleanUpOldFields(newConverter); return { converter: newConverter, topicFilter, subscriptionQos }; - }); + }) as ConverterConnectorMapping[]; } static mapRequestsToUpgradedVersion( requestMapping: Record + LegacyRequestMappingData[]> ): Record { return this.mqttRequestTypeKeys.reduce((acc, key: RequestType) => { if (!requestMapping[key]) { From eb244e3de97e6af8b35c248000a89aa2d13d00d6 Mon Sep 17 00:00:00 2001 From: rusikv Date: Mon, 9 Sep 2024 17:23:47 +0300 Subject: [PATCH 43/80] UI: add origUserFilters optional param for AliasController constructor --- ui-ngx/src/app/core/api/alias-controller.ts | 5 +++-- ui-ngx/src/app/core/api/widget-api.models.ts | 1 + .../components/dashboard-page/dashboard-page.component.ts | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/core/api/alias-controller.ts b/ui-ngx/src/app/core/api/alias-controller.ts index bf7399cf6d..1176e583ae 100644 --- a/ui-ngx/src/app/core/api/alias-controller.ts +++ b/ui-ngx/src/app/core/api/alias-controller.ts @@ -68,10 +68,11 @@ export class AliasController implements IAliasController { private translate: TranslateService, private stateControllerHolder: StateControllerHolder, private origEntityAliases: EntityAliases, - private origFilters: Filters) { + private origFilters: Filters, + private origUserFilters?: Filters) { this.entityAliases = deepClone(this.origEntityAliases) || {}; this.filters = deepClone(this.origFilters) || {}; - this.userFilters = {}; + this.userFilters = deepClone(this.origUserFilters) || {}; } updateEntityAliases(newEntityAliases: EntityAliases) { diff --git a/ui-ngx/src/app/core/api/widget-api.models.ts b/ui-ngx/src/app/core/api/widget-api.models.ts index 71bfa32ee6..5c50ea0ab3 100644 --- a/ui-ngx/src/app/core/api/widget-api.models.ts +++ b/ui-ngx/src/app/core/api/widget-api.models.ts @@ -127,6 +127,7 @@ export interface IAliasController { entityAliasesChanged: Observable>; entityAliasResolved: Observable; filtersChanged: Observable>; + userFilters: Filters; getAliasInfo(aliasId: string): Observable; getEntityAliasId(aliasName: string): string; getInstantAliasInfo(aliasId: string): AliasInfo; diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index 0daabc7611..af0356f4f3 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -522,7 +522,8 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC this.translate, () => this.dashboardCtx.stateController, this.dashboardConfiguration.entityAliases, - this.dashboardConfiguration.filters); + this.dashboardConfiguration.filters, + this.parentDashboard?.aliasController.userFilters); this.updateDashboardCss(); From 00d6f7d5bea16e448dd5aebaee47e9b550996e36 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 9 Sep 2024 17:28:41 +0300 Subject: [PATCH 44/80] UI: Refactor SCADA editor highlighting to support Safari on iOS versions 16.3 and below --- ...metadata-tag-function-panel.component.html | 3 +- ...l-metadata-tag-function-panel.component.ts | 16 +- .../scada-symbol-metadata.component.html | 3 +- .../scada-symbol-metadata.component.ts | 7 +- .../scada-symbol-editor.models.ts | 253 ++++++++++++------ .../shared/components/js-func.component.ts | 35 +-- .../src/app/shared/models/ace/ace.models.ts | 13 +- 7 files changed, 203 insertions(+), 127 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.html index 27c22df7a8..940be57364 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.html @@ -30,8 +30,7 @@ diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts index d46ba364d7..3da729c442 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata-tag-function-panel.component.ts @@ -28,12 +28,10 @@ import { TbPopoverComponent } from '@shared/components/popover.component'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { WidgetService } from '@core/http/widget.service'; import { TbEditorCompleter } from '@shared/models/ace/completion.models'; -import { TbHighlightRule } from '@shared/models/ace/ace.models'; +import { AceHighlightRules } from '@shared/models/ace/ace.models'; import { scadaSymbolClickActionHighlightRules, - scadaSymbolClickActionPropertiesHighlightRules, - scadaSymbolElementStateRenderHighlightRules, - scadaSymbolElementStateRenderPropertiesHighlightRules + scadaSymbolRenderFunctionHighlightRules } from '@home/pages/scada-symbol/scada-symbol-editor.models'; import { JsFuncComponent } from '@shared/components/js-func.component'; @@ -79,9 +77,7 @@ export class ScadaSymbolMetadataTagFunctionPanelComponent implements OnInit, Aft tagFunctionHelpId: string; - objectHighlightRules: TbHighlightRule[]; - - propertyHighlightRules: TbHighlightRule[]; + highlightRules: AceHighlightRules; constructor(private fb: UntypedFormBuilder, private widgetService: WidgetService) { @@ -99,14 +95,12 @@ export class ScadaSymbolMetadataTagFunctionPanelComponent implements OnInit, Aft if (this.tagFunctionType === 'renderFunction') { this.panelTitle = 'scada.state-render-function'; this.tagFunctionArgs = ['ctx', 'element']; - this.objectHighlightRules = scadaSymbolElementStateRenderHighlightRules; - this.propertyHighlightRules = scadaSymbolElementStateRenderPropertiesHighlightRules; + this.highlightRules = scadaSymbolRenderFunctionHighlightRules; this.tagFunctionHelpId = 'scada/tag_state_render_fn'; } else if (this.tagFunctionType === 'clickAction') { this.panelTitle = 'scada.tag.on-click-action'; this.tagFunctionArgs = ['ctx', 'element', 'event']; - this.objectHighlightRules = scadaSymbolClickActionHighlightRules; - this.propertyHighlightRules = scadaSymbolClickActionPropertiesHighlightRules; + this.highlightRules = scadaSymbolClickActionHighlightRules; this.tagFunctionHelpId = 'scada/tag_click_action_fn'; } } diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html index 9e5d22fa94..67c77f7f2a 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.html @@ -80,8 +80,7 @@ diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts index f5ecaab3d2..a5d38991b9 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-metadata.component.ts @@ -49,8 +49,7 @@ import { elementStateRenderFunctionCompletions, generalStateRenderFunctionCompletions, scadaSymbolContextCompletion, - scadaSymbolGeneralStateRenderHighlightRules, - scadaSymbolGeneralStateRenderPropertiesHighlightRules + scadaSymbolGeneralStateHighlightRules } from '@home/pages/scada-symbol/scada-symbol-editor.models'; import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe'; import { IAliasController } from '@core/api/widget-api.models'; @@ -122,9 +121,7 @@ export class ScadaSymbolMetadataComponent extends PageComponent implements OnIni elementStateRenderFunctionCompleter: TbEditorCompleter; clickActionFunctionCompleter: TbEditorCompleter; - scadaSymbolGeneralStateRenderHighlightRules = scadaSymbolGeneralStateRenderHighlightRules; - - scadaSymbolGeneralStateRenderPropertiesHighlightRules = scadaSymbolGeneralStateRenderPropertiesHighlightRules; + highlightRules = scadaSymbolGeneralStateHighlightRules; constructor(protected store: Store, private fb: UntypedFormBuilder, diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts index ddc935d202..433e311fb7 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts @@ -34,7 +34,7 @@ import { } from '@home/components/widget/lib/scada/scada-symbol.models'; import { TbEditorCompletion, TbEditorCompletions } from '@shared/models/ace/completion.models'; import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe'; -import { TbHighlightRule } from '@shared/models/ace/ace.models'; +import { AceHighlightRule, AceHighlightRules } from '@shared/models/ace/ace.models'; import { ValueType } from '@shared/models/constants'; import ITooltipsterInstance = JQueryTooltipster.ITooltipsterInstance; import TooltipPositioningSide = JQueryTooltipster.TooltipPositioningSide; @@ -916,91 +916,184 @@ export class ScadaSymbolElement { } -const scadaSymbolCtxObjectHighlightRules: TbHighlightRule[] = [ - { - class: 'scada-symbol-ctx', - regex: /(?<=\W|^)(ctx)(?=\W|$)\b/ - } -]; +const identifierRe = /[a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*/; -export const scadaSymbolGeneralStateRenderHighlightRules: TbHighlightRule[] = - scadaSymbolCtxObjectHighlightRules.concat({ - class: 'scada-symbol-svg', - regex: /(?<=\W|^)(svg)(?=\W|$)\b/ - }); +const dotOperatorHighlightRule: AceHighlightRule = { + token: 'punctuation.operator', + regex: /[.](?![.])/, +}; -export const scadaSymbolElementStateRenderHighlightRules: TbHighlightRule[] = - scadaSymbolCtxObjectHighlightRules.concat({ - class: 'scada-symbol-element', - regex: /(?<=\W|^)(element)(?=\W|$)\b/ - }); +const endGroupHighlightRule: AceHighlightRule = { + regex: '', + token: 'empty', + next: 'no_regex' +}; -export const scadaSymbolClickActionHighlightRules: TbHighlightRule[] = - scadaSymbolElementStateRenderHighlightRules.concat({ - class: 'scada-symbol-event', - regex: /(?<=\W|^)(event)(?=\W|$)\b/ - }); +const scadaSymbolCtxObjectHighlightRule: AceHighlightRule = { + token: 'tb.scada-symbol-ctx', + regex: /\bctx\b/, + next: 'scadaSymbolCtxApi' +}; -const scadaSymbolCtxPropertyHighlightRules: TbHighlightRule[] = [ - { - class: 'scada-symbol-ctx-properties', - regex: /(?<=ctx\.)(properties)\b/ - }, - { - class: 'scada-symbol-ctx-tags', - regex: /(?<=ctx\.)(tags)\b/ - }, - { - class: 'scada-symbol-ctx-values', - regex: /(?<=ctx\.)(values)\b/ - }, - { - class: 'scada-symbol-ctx-api', - regex: /(?<=ctx\.)(api)\b/ - }, - { - class: 'scada-symbol-ctx-svg', - regex: /(?<=ctx\.)(svg)\b/ - }, - { - class: 'scada-symbol-ctx-property', - regex: /(?<=ctx\.properties\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }, - { - class: 'scada-symbol-ctx-tag', - regex: /(?<=ctx\.tags\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }, - { - class: 'scada-symbol-ctx-value', - regex: /(?<=ctx\.values\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }, - { - class: 'scada-symbol-ctx-api-method', - regex: /(?<=ctx\.api\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }, - { - class: 'scada-symbol-ctx-svg-method', - regex: /(?<=ctx\.svg\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - } -]; - -export const scadaSymbolGeneralStateRenderPropertiesHighlightRules: TbHighlightRule[] = - scadaSymbolCtxPropertyHighlightRules.concat({ - class: 'scada-symbol-svg-properties', - regex: /(?<=svg\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }); +const scadaSymbolSVGHighlightRule: AceHighlightRule = { + token: 'tb.scada-symbol-svg', + regex: /\bsvg\b/, + next: 'scadaSymbolSVGApi' +}; -export const scadaSymbolElementStateRenderPropertiesHighlightRules: TbHighlightRule[] = - scadaSymbolCtxPropertyHighlightRules.concat({ - class: 'scada-symbol-element-properties', - regex: /(?<=element\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }); +const scadaSymbolElementHighlightRule: AceHighlightRule = { + token: 'tb.scada-symbol-element', + regex: /\belement\b/, + next: 'scadaSymbolElementApi' +}; -export const scadaSymbolClickActionPropertiesHighlightRules: TbHighlightRule[] = - scadaSymbolElementStateRenderPropertiesHighlightRules.concat({ - class: 'scada-symbol-event-properties', - regex: /(?<=event\.)([a-zA-Z$_\u00a1-\uffff][a-zA-Z\d$_\u00a1-\uffff]*)\b/ - }); +const scadaSymbolEventHighlightRule: AceHighlightRule = { + token: 'tb.scada-symbol-event', + regex: /\bevent\b/, + next: 'scadaSymbolEventApi' +}; + +const scadaSymbolCtxApiHighlightRules: AceHighlightRules = { + scadaSymbolCtxApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-properties', + regex: /properties/, + next: 'scadaSymbolCtxPropertiesApi' + }, + { + token: 'tb.scada-symbol-ctx-tags', + regex: /tags/, + next: 'scadaSymbolCtxTagsApi' + }, + { + token: 'tb.scada-symbol-ctx-values', + regex: /values/, + next: 'scadaSymbolCtxValuesApi' + }, + { + token: 'tb.scada-symbol-ctx-api', + regex: /api/, + next: 'scadaSymbolCtxApiMethodApi' + }, + { + token: 'tb.scada-symbol-ctx-svg', + regex: /svg/, + next: 'scadaSymbolCtxSVGMethodApi' + }, + endGroupHighlightRule + ], + scadaSymbolCtxPropertiesApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-property', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ], + scadaSymbolCtxTagsApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-tag', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ], + scadaSymbolCtxValuesApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-value', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ], + scadaSymbolCtxApiMethodApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-api-method', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ], + scadaSymbolCtxSVGMethodApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-ctx-svg-method', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ] +}; + +const scadaSymbolSVGPropertyHighlightRules: AceHighlightRules = { + scadaSymbolSVGApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-svg-properties', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ] +}; + +const scadaSymbolElementPropertyHighlightRules: AceHighlightRules = { + scadaSymbolElementApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-element-properties', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ] +}; + +const scadaSymbolEventPropertyHighlightRules: AceHighlightRules = { + scadaSymbolEventApi: [ + dotOperatorHighlightRule, + { + token: 'tb.scada-symbol-event-properties', + regex: identifierRe, + next: 'no_regex' + }, + endGroupHighlightRule + ] +}; + +export const scadaSymbolGeneralStateHighlightRules: AceHighlightRules = { + start: [ + scadaSymbolCtxObjectHighlightRule, + scadaSymbolSVGHighlightRule + ], + ...scadaSymbolCtxApiHighlightRules, + ...scadaSymbolSVGPropertyHighlightRules +}; + +export const scadaSymbolRenderFunctionHighlightRules: AceHighlightRules = { + no_regex: [ + scadaSymbolCtxObjectHighlightRule, + scadaSymbolElementHighlightRule + ], + ...scadaSymbolCtxApiHighlightRules, + ...scadaSymbolElementPropertyHighlightRules +}; + +export const scadaSymbolClickActionHighlightRules: AceHighlightRules = { + start: [ + scadaSymbolCtxObjectHighlightRule, + scadaSymbolElementHighlightRule, + scadaSymbolEventHighlightRule + ], + ...scadaSymbolCtxApiHighlightRules, + ...scadaSymbolElementPropertyHighlightRules, + ...scadaSymbolEventPropertyHighlightRules +}; export const generalStateRenderFunctionCompletions = (ctxCompletion: TbEditorCompletion): TbEditorCompletions => ({ ctx: ctxCompletion, diff --git a/ui-ngx/src/app/shared/components/js-func.component.ts b/ui-ngx/src/app/shared/components/js-func.component.ts index 8c3fa0a423..e15535391f 100644 --- a/ui-ngx/src/app/shared/components/js-func.component.ts +++ b/ui-ngx/src/app/shared/components/js-func.component.ts @@ -25,15 +25,15 @@ import { ViewChild, ViewEncapsulation } from '@angular/core'; -import { ControlValueAccessor, UntypedFormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validator } from '@angular/forms'; +import { ControlValueAccessor, NG_VALIDATORS, NG_VALUE_ACCESSOR, UntypedFormControl, Validator } from '@angular/forms'; import { Ace } from 'ace-builds'; -import { getAce, Range, TbHighlightRule } from '@shared/models/ace/ace.models'; +import { AceHighlightRules, getAce, Range } from '@shared/models/ace/ace.models'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { ActionNotificationHide, ActionNotificationShow } from '@core/notification/notification.actions'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { UtilsService } from '@core/services/utils.service'; -import { deepClone, guid, isUndefined } from '@app/core/utils'; +import { guid, isUndefined } from '@app/core/utils'; import { TranslateService } from '@ngx-translate/core'; import { CancelAnimationFrame, RafService } from '@core/services/raf.service'; import { ResizeObserver } from '@juggle/resize-observer'; @@ -90,9 +90,7 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor, @Input() editorCompleter: TbEditorCompleter; - @Input() propertyHighlightRules: TbHighlightRule[]; - - @Input() objectHighlightRules: TbHighlightRule[]; + @Input() highlightRules: AceHighlightRules; @Input() globalVariables: Array; @@ -220,27 +218,16 @@ export class JsFuncComponent implements OnInit, OnDestroy, ControlValueAccessor, }); } // @ts-ignore - if ((this.propertyHighlightRules?.length || this.objectHighlightRules?.length) && !!this.jsEditor.session.$mode) { + if (!!this.highlightRules && !!this.jsEditor.session.$mode) { // @ts-ignore const newMode = new this.jsEditor.session.$mode.constructor(); newMode.$highlightRules = new newMode.HighlightRules(); - if (this.propertyHighlightRules?.length) { - const propertiesRules: { token: string; regex: RegExp }[] = newMode.$highlightRules.$rules.property; - const index = propertiesRules.findIndex(p => p.token === 'support.constant'); - const additionalPropertyRules: { token: string; regex: RegExp }[] = this.propertyHighlightRules.map(r => ({ - token: `tb.${r.class}`, - regex: r.regex - })); - propertiesRules.splice(index, 0, ...additionalPropertyRules); - } - if (this.objectHighlightRules?.length) { - const noRegexRules: { token: string; regex: RegExp }[] = newMode.$highlightRules.$rules.no_regex; - const index = noRegexRules.findIndex(p => Array.isArray(p.token) && p.token[0] === 'support.constant'); - const additionalNoRegexRules: { token: string; regex: RegExp }[] = this.objectHighlightRules.map(r => ({ - token: `tb.${r.class}`, - regex: r.regex - })); - noRegexRules.splice(index, 0, ...additionalNoRegexRules); + for(const group in this.highlightRules) { + if(!!newMode.$highlightRules.$rules[group]) { + newMode.$highlightRules.$rules[group].unshift(...this.highlightRules[group]); + } else { + newMode.$highlightRules.$rules[group] = this.highlightRules[group]; + } } // @ts-ignore this.jsEditor.session.$onChangeMode(newMode); diff --git a/ui-ngx/src/app/shared/models/ace/ace.models.ts b/ui-ngx/src/app/shared/models/ace/ace.models.ts index 221e68564b..381d897066 100644 --- a/ui-ngx/src/app/shared/models/ace/ace.models.ts +++ b/ui-ngx/src/app/shared/models/ace/ace.models.ts @@ -352,8 +352,15 @@ export class Range implements Ace.Range { } -export interface TbHighlightRule { - class: string; - regex: RegExp; +export interface AceHighlightRules { + [group: string]: Array; } +export interface AceHighlightRule { + regex: RegExp | string; + token: string; + next?: string; +} + + + From 618d82b7ac0385babd566ae97fcb9b8032e4c841 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 9 Sep 2024 17:42:46 +0300 Subject: [PATCH 45/80] Changed approach to GatewayConnector generic --- ...ay-connector-version-processor.abstract.ts | 14 +++++------ .../mqtt-version-processor.abstract.ts | 24 ++++++++++++------- .../models/gateway-configuration.models.ts | 4 +++- .../gateway/gateway-connectors.component.ts | 6 ++--- .../lib/gateway/gateway-widget.models.ts | 16 ++++++++----- .../gateway-connector-version-mapping.util.ts | 8 +++---- 6 files changed, 43 insertions(+), 29 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts index 31b8ba8cf8..923cf1920b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts @@ -4,23 +4,23 @@ export abstract class GatewayConnectorVersionProcessor { gatewayVersion: number; configVersion: number; - protected constructor(protected gatewayVersionStr: string, protected connector: GatewayConnector) { + protected constructor(protected gatewayVersionStr: string, protected connector: GatewayConnector) { this.gatewayVersion = this.parseVersion(this.gatewayVersionStr); this.configVersion = this.parseVersion(connector.configVersion); } - getProcessedByVersion(): BasicConfig { + getProcessedByVersion(): GatewayConnector { if (this.isVersionUpdateNeeded()) { - return this.configVersion < this.gatewayVersion + return !this.configVersion || this.configVersion < this.gatewayVersion ? this.getUpgradedVersion() : this.getDowngradedVersion(); } - return this.connector.configurationJson as unknown as BasicConfig; + return this.connector; } private isVersionUpdateNeeded(): boolean { - if (!this.gatewayVersion || !this.configVersion) { + if (!this.gatewayVersion) { return false; } @@ -31,6 +31,6 @@ export abstract class GatewayConnectorVersionProcessor { return Number(version?.replace(/\./g, '')); } - abstract getDowngradedVersion(): BasicConfig; - abstract getUpgradedVersion(): BasicConfig; + abstract getDowngradedVersion(): GatewayConnector; + abstract getUpgradedVersion(): GatewayConnector; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts index 875b238d7e..99591130a5 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts @@ -15,11 +15,11 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor ) { super(gatewayVersionStr, connector); } - getUpgradedVersion(): MQTTBasicConfig_v3_5_2 { + getUpgradedVersion(): GatewayConnector { const { connectRequests, disconnectRequests, @@ -46,10 +46,14 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor; } - getDowngradedVersion(): MQTTLegacyBasicConfig { + getDowngradedVersion(): GatewayConnector { const { requestsMapping, mapping, ...restConfig } = this.connector.configurationJson as MQTTBasicConfig_v3_5_2; const updatedRequestsMapping = @@ -57,10 +61,14 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor; } private cleanUpConfigJson(configurationJson: MQTTBasicConfig_v3_5_2): void { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/models/gateway-configuration.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/models/gateway-configuration.models.ts index a23d8e7900..bfdd46997e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/models/gateway-configuration.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/configuration/models/gateway-configuration.models.ts @@ -16,7 +16,9 @@ import { ConfigurationModes, - GatewayConnector, LocalLogsConfigs, LogSavingPeriod, + GatewayConnector, + LocalLogsConfigs, + LogSavingPeriod, SecurityTypes, StorageTypes } from '@home/components/widget/lib/gateway/gateway-widget.models'; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index b6e2dfc093..cbaeed8888 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -732,14 +732,14 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie this.connectorForm.enable(); } - const connectorState = { + const connectorState = GatewayConnectorVersionMappingUtil.getConfig({ configuration: '', key: 'auto', configurationJson: {} as ConnectorBaseConfig, ...connector, - }; + }, this.gatewayVersion); - connectorState.basicConfig = GatewayConnectorVersionMappingUtil.getConfig(connectorState, this.gatewayVersion); + connectorState.basicConfig = connectorState.configurationJson; this.initialConnector = connectorState; this.updateConnector(connectorState); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 38040f15d3..94d8ce7d2a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -124,14 +124,14 @@ export interface GatewayConnectorBase { configVersion?: string; } -export interface GatewayConnector extends GatewayConnectorBase { - configurationJson: ConnectorBaseConfig; - basicConfig?: ConnectorBaseConfig; +export interface GatewayConnector extends GatewayConnectorBase { + configurationJson: BaseConfig; + basicConfig?: BaseConfig; } export interface GatewayVersionedDefaultConfig { - legacy: GatewayConnector; - '3.5.1': GatewayConnector; + legacy: GatewayConnector; + '3.5.1': GatewayConnector; } export interface DataMapping { @@ -192,7 +192,11 @@ export type ConnectorMapping = DeviceConnectorMapping | RequestMappingValue | Co export type ConnectorMappingFormValue = DeviceConnectorMapping | RequestMappingFormValue | ConverterMappingFormValue; -export type ConnectorBaseConfig = ConnectorBaseInfo | MQTTBasicConfig | OPCBasicConfig | ModbusBasicConfig; +export type ConnectorBaseConfig = ConnectorBaseConfig_v_3_5_2 | ConnectorLegacyConfig; + +export type ConnectorLegacyConfig = ConnectorBaseInfo | MQTTLegacyBasicConfig | OPCBasicConfig | ModbusBasicConfig; + +export type ConnectorBaseConfig_v_3_5_2 = ConnectorBaseInfo | MQTTBasicConfig_v3_5_2; export interface ConnectorBaseInfo { name: string; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts index ab9e393fee..9de53e506d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts @@ -17,18 +17,18 @@ import { ConnectorBaseConfig, ConnectorType, - GatewayConnector, + GatewayConnector, MQTTBasicConfig, } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { MqttVersionProcessor } from '@home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract'; export abstract class GatewayConnectorVersionMappingUtil { - static getConfig(connector: GatewayConnector, gatewayVersion: string): ConnectorBaseConfig { + static getConfig(connector: GatewayConnector, gatewayVersion: string): GatewayConnector { switch(connector.type) { case ConnectorType.MQTT: - return new MqttVersionProcessor(gatewayVersion, connector).getProcessedByVersion(); + return new MqttVersionProcessor(gatewayVersion, connector as GatewayConnector).getProcessedByVersion(); default: - return connector.configurationJson as ConnectorBaseConfig; + return connector; } } } From 189778efb9ca9fda662fb8508e5ba1f812aa64a2 Mon Sep 17 00:00:00 2001 From: ThingsBoard Bot Date: Mon, 9 Sep 2024 14:57:22 +0000 Subject: [PATCH 46/80] License header format --- .../server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java b/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java index ab132912fc..2d6a50cea4 100644 --- a/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java +++ b/common/queue/src/test/java/org/thingsboard/server/queue/rabbitmq/TbRabbitMqConsumerTemplateTest.java @@ -1,5 +1,5 @@ /** - * Copyright © 2016-2023 The Thingsboard Authors + * Copyright © 2016-2024 The Thingsboard Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From c1963898490fb82969637d9b789679ee1f251d97 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 9 Sep 2024 18:01:04 +0300 Subject: [PATCH 47/80] UI: Add default layout type to old grid settings. --- .../src/app/core/services/dashboard-utils.service.ts | 12 ++++++++---- ui-ngx/src/app/shared/models/dashboard.models.ts | 1 - 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ui-ngx/src/app/core/services/dashboard-utils.service.ts b/ui-ngx/src/app/core/services/dashboard-utils.service.ts index 5c2363789d..b31c603814 100644 --- a/ui-ngx/src/app/core/services/dashboard-utils.service.ts +++ b/ui-ngx/src/app/core/services/dashboard-utils.service.ts @@ -31,7 +31,7 @@ import { DashboardLayoutsInfo, DashboardState, DashboardStateLayouts, - GridSettings, + GridSettings, LayoutType, WidgetLayout } from '@shared/models/dashboard.models'; import { deepClone, isDefined, isDefinedAndNotNull, isNotEmptyStr, isString, isUndefined } from '@core/utils'; @@ -406,6 +406,7 @@ export class DashboardUtilsService { private createDefaultGridSettings(): GridSettings { return { + layoutType: LayoutType.default, backgroundColor: '#eeeeee', columns: 24, margin: 10, @@ -491,12 +492,15 @@ export class DashboardUtilsService { if (!layout.gridSettings) { layout.gridSettings = this.createDefaultGridSettings(); } - if (layout.gridSettings.margins && layout.gridSettings.margins.length === 2) { - layout.gridSettings.margin = layout.gridSettings.margins[0]; - delete layout.gridSettings.margins; + if ((layout.gridSettings as any).margins && (layout.gridSettings as any).margins.length === 2) { + layout.gridSettings.margin = (layout.gridSettings as any).margins[0]; + delete (layout.gridSettings as any).margins; } layout.gridSettings.outerMargin = isDefined(layout.gridSettings.outerMargin) ? layout.gridSettings.outerMargin : true; layout.gridSettings.margin = isDefined(layout.gridSettings.margin) ? layout.gridSettings.margin : 10; + if (!layout.gridSettings.layoutType) { + layout.gridSettings.layoutType = LayoutType.default; + } } public setLayouts(dashboard: Dashboard, targetState: string, newLayouts: DashboardStateLayouts) { diff --git a/ui-ngx/src/app/shared/models/dashboard.models.ts b/ui-ngx/src/app/shared/models/dashboard.models.ts index c4e767b314..45f4eb8cf2 100644 --- a/ui-ngx/src/app/shared/models/dashboard.models.ts +++ b/ui-ngx/src/app/shared/models/dashboard.models.ts @@ -97,7 +97,6 @@ export interface GridSettings { mobileRowHeight?: number; mobileDisplayLayoutFirst?: boolean; layoutDimension?: LayoutDimension; - [key: string]: any; } export interface DashboardLayout { From 53d86dd31ef098ebfa4a37babcb6fc438f50f98e Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 9 Sep 2024 18:21:33 +0300 Subject: [PATCH 48/80] refactoring --- .../abstract/gateway-connector-version-processor.abstract.ts | 4 ++-- .../mqtt/basic-config/mqtt-basic-config.abstract.ts | 2 +- .../mqtt/basic-config/mqtt-basic-config.component.html | 4 ++-- .../gateway/utils/gateway-connector-version-mapping.util.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts index 923cf1920b..579ad6a45b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts @@ -31,6 +31,6 @@ export abstract class GatewayConnectorVersionProcessor { return Number(version?.replace(/\./g, '')); } - abstract getDowngradedVersion(): GatewayConnector; - abstract getUpgradedVersion(): GatewayConnector; + protected abstract getDowngradedVersion(): GatewayConnector; + protected abstract getUpgradedVersion(): GatewayConnector; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts index 0394604d42..aeef688333 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts @@ -31,7 +31,7 @@ import { isObject } from '@core/utils'; export abstract class AbstractMqttBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy { basicFormGroup: FormGroup; - mappingTypes = MappingType; + MappingType = MappingType; private destroy$ = new Subject(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.html index 9ad25aa851..b602ba20d4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.html @@ -24,12 +24,12 @@
- +
- +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts index 9de53e506d..12f3a7c439 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts @@ -15,9 +15,9 @@ /// import { - ConnectorBaseConfig, ConnectorType, - GatewayConnector, MQTTBasicConfig, + GatewayConnector, + MQTTBasicConfig, } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { MqttVersionProcessor } from '@home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract'; From 625e400d2b4e89a68b0a7416b3dd6b6b45961132 Mon Sep 17 00:00:00 2001 From: rusikv Date: Mon, 9 Sep 2024 18:26:54 +0300 Subject: [PATCH 49/80] UI: refactor getting of user filters in alias controller interface --- ui-ngx/src/app/core/api/alias-controller.ts | 4 ++++ ui-ngx/src/app/core/api/widget-api.models.ts | 2 +- .../components/dashboard-page/dashboard-page.component.ts | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/core/api/alias-controller.ts b/ui-ngx/src/app/core/api/alias-controller.ts index 1176e583ae..83dd4e102f 100644 --- a/ui-ngx/src/app/core/api/alias-controller.ts +++ b/ui-ngx/src/app/core/api/alias-controller.ts @@ -167,6 +167,10 @@ export class AliasController implements IAliasController { return this.filters; } + getUserFilters(): Filters { + return this.userFilters; + } + getFilterInfo(filterId: string): FilterInfo { if (this.userFilters[filterId]) { return this.userFilters[filterId]; diff --git a/ui-ngx/src/app/core/api/widget-api.models.ts b/ui-ngx/src/app/core/api/widget-api.models.ts index 5c50ea0ab3..bca6a05644 100644 --- a/ui-ngx/src/app/core/api/widget-api.models.ts +++ b/ui-ngx/src/app/core/api/widget-api.models.ts @@ -127,7 +127,6 @@ export interface IAliasController { entityAliasesChanged: Observable>; entityAliasResolved: Observable; filtersChanged: Observable>; - userFilters: Filters; getAliasInfo(aliasId: string): Observable; getEntityAliasId(aliasName: string): string; getInstantAliasInfo(aliasId: string): AliasInfo; @@ -138,6 +137,7 @@ export interface IAliasController { resolveAlarmSource(alarmSource: Datasource): Observable; getEntityAliases(): EntityAliases; getFilters(): Filters; + getUserFilters(): Filters; getFilterInfo(filterId: string): FilterInfo; getKeyFilters(filterId: string): Array; updateCurrentAliasEntity(aliasId: string, currentEntity: EntityInfo): void; diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts index af0356f4f3..5dacda4733 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts @@ -523,7 +523,7 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC () => this.dashboardCtx.stateController, this.dashboardConfiguration.entityAliases, this.dashboardConfiguration.filters, - this.parentDashboard?.aliasController.userFilters); + this.parentDashboard?.aliasController.getUserFilters()); this.updateDashboardCss(); From 13e7e4a61d356453900befd5ef77df11f1feda5f Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 9 Sep 2024 18:39:26 +0300 Subject: [PATCH 50/80] [4114] Updated version checks --- .../gateway-connector-version-processor.abstract.ts | 8 ++++++-- .../lib/gateway/dialog/add-connector-dialog.component.ts | 3 ++- .../widget/lib/gateway/gateway-connectors.component.html | 2 +- .../widget/lib/gateway/gateway-connectors.component.ts | 2 ++ .../widget/lib/gateway/gateway-widget.models.ts | 5 +++++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts index 579ad6a45b..b2062e428b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts @@ -1,4 +1,4 @@ -import { GatewayConnector } from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { GatewayConnector, GatewayVersion } from '@home/components/widget/lib/gateway/gateway-widget.models'; export abstract class GatewayConnectorVersionProcessor { gatewayVersion: number; @@ -11,7 +11,7 @@ export abstract class GatewayConnectorVersionProcessor { getProcessedByVersion(): GatewayConnector { if (this.isVersionUpdateNeeded()) { - return !this.configVersion || this.configVersion < this.gatewayVersion + return this.isVersionUpgradeNeeded() ? this.getUpgradedVersion() : this.getDowngradedVersion(); } @@ -27,6 +27,10 @@ export abstract class GatewayConnectorVersionProcessor { return this.configVersion !== this.gatewayVersion; } + private isVersionUpgradeNeeded(): boolean { + return (!this.configVersion || this.configVersion < this.gatewayVersion) && this.gatewayVersionStr === GatewayVersion.Current; + } + private parseVersion(version: string): number { return Number(version?.replace(/\./g, '')); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts index 0168cf86af..c8235cb697 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/dialog/add-connector-dialog.component.ts @@ -29,6 +29,7 @@ import { GatewayConnector, GatewayConnectorDefaultTypesTranslatesMap, GatewayLogLevel, + GatewayVersion, GatewayVersionedDefaultConfig, noLeadTrailSpacesRegex } from '@home/components/widget/lib/gateway/gateway-widget.models'; @@ -102,7 +103,7 @@ export class AddConnectorDialogComponent if (gatewayVersion) { value.configVersion = gatewayVersion; } - value.configurationJson = (gatewayVersion + value.configurationJson = (gatewayVersion === GatewayVersion.Current ? defaultConfig[this.data.gatewayVersion] : defaultConfig.legacy) ?? defaultConfig; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html index 63a18ad3d2..f0459496df 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html @@ -178,7 +178,7 @@ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index cbaeed8888..9be5b550ce 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -59,6 +59,7 @@ import { GatewayConnectorDefaultTypesTranslatesMap, GatewayLogLevel, noLeadTrailSpacesRegex, + GatewayVersion, } from './gateway-widget.models'; import { MatDialog } from '@angular/material/dialog'; import { AddConnectorDialogComponent } from '@home/components/widget/lib/gateway/dialog/add-connector-dialog.component'; @@ -101,6 +102,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie readonly displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions']; readonly GatewayConnectorTypesTranslatesMap = GatewayConnectorDefaultTypesTranslatesMap; readonly ConnectorConfigurationModes = ConfigurationModes; + readonly GatewayVersion = GatewayVersion; pageLink: PageLink; dataSource: MatTableDataSource; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 94d8ce7d2a..f7acac12e6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -188,6 +188,11 @@ export interface ConnectorSecurity { mode?: ModeType; } +export enum GatewayVersion { + Current = '3.5.1', + Legacy = 'legacy' +} + export type ConnectorMapping = DeviceConnectorMapping | RequestMappingValue | ConverterConnectorMapping; export type ConnectorMappingFormValue = DeviceConnectorMapping | RequestMappingFormValue | ConverterMappingFormValue; From 4323c6abd2bc3f911b28a0cb134a8503c9bb06d8 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 9 Sep 2024 19:10:49 +0300 Subject: [PATCH 51/80] [4114] refactoring --- .../abstract/gateway-connector-version-processor.abstract.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts index b2062e428b..cad9300212 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts @@ -28,7 +28,7 @@ export abstract class GatewayConnectorVersionProcessor { } private isVersionUpgradeNeeded(): boolean { - return (!this.configVersion || this.configVersion < this.gatewayVersion) && this.gatewayVersionStr === GatewayVersion.Current; + return this.gatewayVersionStr === GatewayVersion.Current && (!this.configVersion || this.configVersion < this.gatewayVersion); } private parseVersion(version: string): number { From 1625f435b380faf1f23f58a02b18d3077d70447f Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 9 Sep 2024 19:11:37 +0300 Subject: [PATCH 52/80] [4114] license headers --- ...teway-connector-version-processor.abstract.ts | 16 ++++++++++++++++ .../abstract/mqtt-version-processor.abstract.ts | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts index cad9300212..e1addf0b71 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts @@ -1,3 +1,19 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + import { GatewayConnector, GatewayVersion } from '@home/components/widget/lib/gateway/gateway-widget.models'; export abstract class GatewayConnectorVersionProcessor { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts index 99591130a5..645eb64fa4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts @@ -1,3 +1,19 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + import { isEqual } from '@core/utils'; import { GatewayConnector, From f0e56ab02cf7dd8bc1b446bfd6aefc8a39811452 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 9 Sep 2024 19:39:58 +0300 Subject: [PATCH 53/80] DashboardEdgeTest - fixed err msg related to incorrect image format --- .../server/edge/DashboardEdgeTest.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java index b6311da80a..3b252046ab 100644 --- a/application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java +++ b/application/src/test/java/org/thingsboard/server/edge/DashboardEdgeTest.java @@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.dao.service.DaoSqlTest; import org.thingsboard.server.gen.edge.v1.DashboardUpdateMsg; +import org.thingsboard.server.gen.edge.v1.ResourceUpdateMsg; import org.thingsboard.server.gen.edge.v1.UpdateMsgType; import org.thingsboard.server.gen.edge.v1.UplinkMsg; @@ -44,12 +45,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. public class DashboardEdgeTest extends AbstractEdgeTest { private static final int MOBILE_ORDER = 5; - private static final String IMAGE = "data:image/png;base64,iVBORw0KGgoA"; + private static final String IMAGE = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+"; @Test public void testDashboards() throws Exception { // create dashboard and assign to edge - edgeImitator.expectMessageAmount(1); + edgeImitator.expectMessageAmount(2); Dashboard dashboard = new Dashboard(); dashboard.setTitle("Edge Test Dashboard"); dashboard.setMobileHide(true); @@ -59,23 +60,26 @@ public class DashboardEdgeTest extends AbstractEdgeTest { doPost("/api/edge/" + edge.getUuidId() + "/dashboard/" + savedDashboard.getUuidId(), Dashboard.class); Assert.assertTrue(edgeImitator.waitForMessages()); - AbstractMessage latestMessage = edgeImitator.getLatestMessage(); - Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); - DashboardUpdateMsg dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; + Optional dashboardUpdateMsgOpt = edgeImitator.findMessageByType(DashboardUpdateMsg.class); + Assert.assertTrue(dashboardUpdateMsgOpt.isPresent()); + DashboardUpdateMsg dashboardUpdateMsg = dashboardUpdateMsgOpt.get(); Dashboard dashboardMsg = JacksonUtil.fromString(dashboardUpdateMsg.getEntity(), Dashboard.class, true); Assert.assertNotNull(dashboardMsg); Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, dashboardUpdateMsg.getMsgType()); Assert.assertEquals(savedDashboard, dashboardMsg); - Assert.assertEquals(IMAGE, dashboardMsg.getImage()); + Assert.assertEquals("tb-image;/api/images/tenant/edge_test_dashboard_dashboard_image.svg", dashboardMsg.getImage()); Assert.assertEquals(MOBILE_ORDER, dashboardMsg.getMobileOrder().intValue()); testAutoGeneratedCodeByProtobuf(dashboardUpdateMsg); + Optional resourceUpdateMsg = edgeImitator.findMessageByType(ResourceUpdateMsg.class); + Assert.assertTrue(resourceUpdateMsg.isPresent()); + // update dashboard edgeImitator.expectMessageAmount(1); savedDashboard.setTitle("Updated Edge Test Dashboard"); savedDashboard = doPost("/api/dashboard", savedDashboard, Dashboard.class); Assert.assertTrue(edgeImitator.waitForMessages()); - latestMessage = edgeImitator.getLatestMessage(); + AbstractMessage latestMessage = edgeImitator.getLatestMessage(); Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg); dashboardUpdateMsg = (DashboardUpdateMsg) latestMessage; dashboardMsg = JacksonUtil.fromString(dashboardUpdateMsg.getEntity(), Dashboard.class, true); From 1f48fbb48cc8c1b2f7d657fd9580e9bc8e7e2440 Mon Sep 17 00:00:00 2001 From: YevhenBondarenko Date: Mon, 9 Sep 2024 23:27:14 +0200 Subject: [PATCH 54/80] added description to the rabbitmq max_poll_messages property --- application/src/main/resources/thingsboard.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml index c3356f2bba..e1893511f3 100644 --- a/application/src/main/resources/thingsboard.yml +++ b/application/src/main/resources/thingsboard.yml @@ -1658,6 +1658,7 @@ queue: connection_timeout: "${TB_QUEUE_RABBIT_MQ_CONNECTION_TIMEOUT:60000}" # RabbitMQ has a timeout for connection handshake. When clients run in heavily constrained environments, it may be necessary to increase the timeout handshake_timeout: "${TB_QUEUE_RABBIT_MQ_HANDSHAKE_TIMEOUT:10000}" + # The maximum number of messages returned in a single call of doPoll() method max_poll_messages: "${TB_QUEUE_RABBIT_MQ_MAX_POLL_MESSAGES:1}" queue-properties: # RabbitMQ properties for Rule Engine queues From e43a82028e836c75f68829d951193e73f29e3283 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Tue, 10 Sep 2024 10:22:10 +0300 Subject: [PATCH 55/80] UI: Refactoring image --- .../data/json/system/widget_bundles/scada_fluid_system.json | 2 +- .../src/main/data/json/system/widget_bundles/scada_symbols.json | 2 +- .../src/main/data/json/system/widget_types/scada_symbol.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json b/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json index 405185ae21..7ec1a0d60f 100644 --- a/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json +++ b/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json @@ -2,7 +2,7 @@ "widgetsBundle": { "alias": "scada_fluid_system", "title": "SCADA fluid system", - "image": "tb-image:c2NhZGFfZmx1aWRfc3lzdGVtX2J1bmRsZV9pbWFnZS5wbmc=:IlNDQURBIGZsdWlkIHN5c3RlbSIgc3lzdGVtIGJ1bmRsZSBpbWFnZQ==:SU1BR0U=;data:image/png;base64,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", + "image": "tb-image:c2NhZGFfZmx1aWRfc3lzdGVtX2J1bmRsZV9pbWFnZV8oMSkucG5n:IlNDQURBIGZsdWlkIHN5c3RlbSIgc3lzdGVtIGJ1bmRsZSBpbWFnZQ==:SU1BR0U=;data:image/png;base64,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", "scada": true, "description": "Bundle with SCADA symbols for fluid system", "order": 9300, diff --git a/application/src/main/data/json/system/widget_bundles/scada_symbols.json b/application/src/main/data/json/system/widget_bundles/scada_symbols.json index 803a3a9126..4de61d2b05 100644 --- a/application/src/main/data/json/system/widget_bundles/scada_symbols.json +++ b/application/src/main/data/json/system/widget_bundles/scada_symbols.json @@ -3,7 +3,7 @@ "alias": "scada_symbols", "title": "SCADA symbols", "scada": true, - "image": "tb-image:c2NhZGFfc3ltYm9sc19zeXN0ZW1fYnVuZGxlX2ltYWdlLnBuZw==:IlNDQURBIHN5bWJvbHMiIHN5c3RlbSBidW5kbGUgaW1hZ2U=:SU1BR0U=;data:image/png;base64,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", + "image": "tb-image:c2NhZGFfc3ltYm9sc19zeXN0ZW1fYnVuZGxlX2ltYWdlXygxKS5zdmc=:IlNDQURBIHN5bWJvbHMiIHN5c3RlbSBidW5kbGUgaW1hZ2U=:SU1BR0U=;data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJtMTI2LjA0MiAzNS42NjY2LTIyLjkxNy0xMy4yNWMtMS45MTctMS4xMjUtNC4zMzMzLTEuMTI1LTYuMjUgMGwtMjIuOTE2NyAxMy4yNWMtMS45MTY2IDEuMTI1LTMuMTI1IDMuMTY2Ny0zLjEyNSA1LjQxNjd2MjYuNDU4M2MwIDIuMjUgMS4yMDg0IDQuMjkxNiAzLjEyNSA1LjQxNjZsMjIuOTE2NyAxMy4yNWMxLjkxNjcgMS4xMjUgNC4zMzMgMS4xMjUgNi4yNSAwbDIyLjkxNy0xMy4yNWMxLjkxNi0xLjEyNSAzLjEyNS0zLjE2NjYgMy4xMjUtNS40MTY2VjQxLjA4MzNjMC0yLjI1LTEuMjA5LTQuMjkxNy0zLjEyNS01LjQxNjdaTTc5LjE2NjcgNjYuMzMzM3YtMTkuMjVsMTYuNjY2NiA5LjY2NjZ2MTkuMjA4NGwtMTYuNjY2Ni05LjYyNVpNMTAwIDQ5LjU0MTZsLTE2LjY2NjctOS42NjY3TDEwMCAzMC4yNDk5bDE2LjY2NyA5LjYyNUwxMDAgNDkuNTQxNlptNC4xNjcgMjYuNDE2N1Y1Ni43NDk5bDE2LjY2Ni05LjY2NjZ2MTkuMjVsLTE2LjY2NiA5LjYyNVptLTI1LjAwMDMtNjMuNjI1SDY0LjU4MzNjLTMuNDU4MyAwLTYuMjUgMi43OTE2LTYuMjUgNi4yNXYxNC41ODMzaDguMzMzNHYtMTIuNWgxMi41di04LjMzMzNabTQxLjY2NjMgMGgxNC41ODRjMy40NTggMCA2LjI1IDIuNzkxNiA2LjI1IDYuMjV2MTQuNTgzM2gtOC4zMzR2LTEyLjVoLTEyLjV2LTguMzMzM1pNNzkuMTY2NyA5NS42NjY2SDY0LjU4MzNjLTMuNDU4MyAwLTYuMjUtMi43OTE3LTYuMjUtNi4yNVY3NC44MzMyaDguMzMzNHYxMi41MDAxaDEyLjV2OC4zMzMzWm00MS42NjYzIDBoMTQuNTg0YzMuNDU4IDAgNi4yNS0yLjc5MTcgNi4yNS02LjI1Vjc0LjgzMzJoLTguMzM0djEyLjUwMDFoLTEyLjV2OC4zMzMzWiIgZmlsbD0iIzMwNTY4MCIgZmlsbC1vcGFjaXR5PSIuNiIvPjxwYXRoIGQ9Ik02Mi41ODI4IDEyMS42MjVoNC4wMjM1Yy44NjQ1IDAgMS42MDE1LjEzIDIuMjEwOS4zOTEuNjA5NC4yNiAxLjA3NTUuNjQ1IDEuMzk4NCAxLjE1Ni4zMjgyLjUwNS40OTIyIDEuMTMuNDkyMiAxLjg3NSAwIC41NjgtLjEwNDIgMS4wNjgtLjMxMjUgMS41LS4yMDgzLjQzMi0uNTAyNi43OTctLjg4MjggMS4wOTQtLjM4MDIuMjkxLS44MzMzLjUxOC0xLjM1OTQuNjc5bC0uNTkzNy4yODloLTMuNjE3MmwtLjAxNTYtMS41NTRoMi43MTA5Yy40Njg4IDAgLjg1OTQtLjA4NCAxLjE3MTktLjI1LjMxMjUtLjE2Ny41NDY5LS4zOTQuNzAzMS0uNjguMTYxNS0uMjkyLjI0MjItLjYyLjI0MjItLjk4NCAwLS4zOTYtLjA3ODEtLjc0LS4yMzQ0LTEuMDMyLS4xNTEtLjI5Ny0uMzg1NC0uNTIzLS43MDMxLS42NzktLjMxNzctLjE2Mi0uNzIxNC0uMjQyLTEuMjEwOS0uMjQyaC0yLjA2MjVWMTMzaC0xLjk2MXYtMTEuMzc1Wk02OS4wNzUgMTMzbC0yLjY3MTktNS4xMDkgMi4wNTQ3LS4wMDggMi43MTEgNS4wMTVWMTMzSDY5LjA3NVptNy4zMjUuMTU2Yy0uNjI1IDAtMS4xOTAxLS4xMDEtMS42OTUzLS4zMDQtLjUtLjIwOS0uOTI3MS0uNDk4LTEuMjgxMy0uODY4LS4zNDg5LS4zNjktLjYxNzEtLjgwNC0uODA0Ni0xLjMwNHMtLjI4MTMtMS4wMzktLjI4MTMtMS42MTh2LS4zMTJjMC0uNjYxLjA5NjQtMS4yNi4yODkxLTEuNzk3LjE5MjctLjUzNi40NjA5LS45OTUuODA0Ny0xLjM3NS4zNDM3LS4zODUuNzUtLjY4IDEuMjE4Ny0uODgzLjQ2ODgtLjIwMy45NzY2LS4zMDQgMS41MjM0LS4zMDQuNjA0MiAwIDEuMTMyOS4xMDEgMS41ODYuMzA0LjQ1MzEuMjAzLjgyODEuNDkgMS4xMjUuODYuMzAyMS4zNjQuNTI2Ljc5OS42NzE5IDEuMzA0LjE1MS41MDYuMjI2NSAxLjA2My4yMjY1IDEuNjcydi44MDVoLTYuNTMxMnYtMS4zNTJoNC42NzE4di0uMTQ4Yy0uMDEwNC0uMzM5LS4wNzgxLS42NTYtLjIwMzEtLjk1My0uMTE5OC0uMjk3LS4zMDQ3LS41MzctLjU1NDctLjcxOS0uMjUtLjE4Mi0uNTgzMy0uMjczLTEtLjI3My0uMzEyNSAwLS41OTExLjA2Ny0uODM1OS4yMDMtLjIzOTYuMTMtLjQ0MDEuMzItLjYwMTYuNTctLjE2MTQuMjUtLjI4NjQuNTUyLS4zNzUuOTA2LS4wODMzLjM0OS0uMTI1Ljc0Mi0uMTI1IDEuMTh2LjMxMmMwIC4zNy4wNDk1LjcxNC4xNDg1IDEuMDMyLjEwNDEuMzEyLjI1NTIuNTg2LjQ1MzEuODIuMTk3OS4yMzQuNDM3NS40MTkuNzE4Ny41NTUuMjgxMy4xMy42MDE2LjE5NS45NjEuMTk1LjQ1MzEgMCAuODU2Ny0uMDkxIDEuMjEwOS0uMjczLjM1NDItLjE4My42NjE1LS40NC45MjE5LS43NzRsLjk5MjIuOTYxYy0uMTgyMy4yNjYtLjQxOTMuNTIxLS43MTEuNzY2LS4yOTE2LjIzOS0uNjQ4NC40MzUtMS4wNzAzLjU4Ni0uNDE2Ni4xNTEtLjkwMS4yMjYtMS40NTMxLjIyNlptOS43OTM3LTIuNDQ1YzAtLjE4OC0uMDQ2OC0uMzU3LS4xNDA2LS41MDgtLjA5MzctLjE1Ni0uMjczNC0uMjk3LS41MzktLjQyMi0uMjYwNS0uMTI1LS42NDU5LS4yMzktMS4xNTYzLS4zNDMtLjQ0NzktLjA5OS0uODU5NC0uMjE3LTEuMjM0NC0uMzUyLS4zNjk4LS4xNDEtLjY4NzUtLjMxLS45NTMxLS41MDgtLjI2NTYtLjE5OC0uNDcxMy0uNDMyLS42MTcyLS43MDMtLjE0NTgtLjI3MS0uMjE4Ny0uNTgzLS4yMTg3LS45MzcgMC0uMzQ0LjA3NTUtLjY3LjIyNjUtLjk3Ny4xNTExLS4zMDcuMzY3Mi0uNTc4LjY0ODUtLjgxMy4yODEyLS4yMzQuNjIyNC0uNDE5IDEuMDIzNC0uNTU0LjQwNjMtLjEzNi44NTk0LS4yMDMgMS4zNTk0LS4yMDMuNzA4MyAwIDEuMzE1MS4xMTkgMS44MjAzLjM1OS41MTA0LjIzNC45MDEuNTU1IDEuMTcxOS45NjEuMjcwOC40MDEuNDA2Mi44NTQuNDA2MiAxLjM1OWgtMS44ODI4YzAtLjIyNC0uMDU3My0uNDMyLS4xNzE5LS42MjUtLjEwOTMtLjE5OC0uMjc2LS4zNTYtLjUtLjQ3Ni0uMjIzOS0uMTI1LS41MDUyLS4xODgtLjg0MzctLjE4OC0uMzIyOSAwLS41OTEyLjA1Mi0uODA0Ny4xNTctLjIwODMuMDk4LS4zNjQ2LjIyOS0uNDY4OC4zOWExIDEgMCAwIDAtLjE0ODQuNTMxYzAgLjE0MS4wMjYxLjI2OS4wNzgxLjM4My4wNTczLjExLjE1MTEuMjExLjI4MTMuMzA1LjEzMDIuMDg4LjMwNzMuMTcyLjUzMTIuMjUuMjI5Mi4wNzguNTE1Ny4xNTQuODU5NC4yMjYuNjQ1OC4xMzYgMS4yMDA1LjMxIDEuNjY0MS41MjQuNDY4Ny4yMDguODI4MS40NzkgMS4wNzgxLjgxMi4yNS4zMjkuMzc1Ljc0NS4zNzUgMS4yNSAwIC4zNzUtLjA4MDcuNzE5LS4yNDIyIDEuMDMyLS4xNTYyLjMwNy0uMzg1NC41NzUtLjY4NzUuODA0LS4zMDIxLjIyNC0uNjY0MS4zOTktMS4wODU5LjUyNC0uNDE2Ny4xMjUtLjg4NTQuMTg3LTEuNDA2My4xODctLjc2NTYgMC0xLjQxNC0uMTM1LTEuOTQ1My0uNDA2LS41MzEyLS4yNzYtLjkzNDktLjYyOC0xLjIxMDktMS4wNTUtLjI3MDktLjQzMi0uNDA2My0uODgtLjQwNjMtMS4zNDNoMS44MjAzYy4wMjA5LjM0OS4xMTcyLjYyNy4yODkxLjgzNi4xNzcxLjIwMy4zOTU4LjM1MS42NTYyLjQ0NS4yNjU3LjA4OC41MzkxLjEzMy44MjA0LjEzMy4zMzg1IDAgLjYyMjQtLjA0NS44NTE1LS4xMzMuMjI5Mi0uMDk0LjQwMzctLjIxOS41MjM1LS4zNzUuMTE5OC0uMTYyLjE3OTYtLjM0NC4xNzk2LS41NDdabTMuMzMyOS0xLjg0NHYtLjE3OWMwLS42MS4wODg1LTEuMTc1LjI2NTYtMS42OTYuMTc3MS0uNTI2LjQzMjMtLjk4Mi43NjU2LTEuMzY3LjMzODYtLjM5MS43NS0uNjkzIDEuMjM0NC0uOTA2LjQ4OTYtLjIxOSAxLjA0MTctLjMyOCAxLjY1NjItLjMyOC42MTk4IDAgMS4xNzE5LjEwOSAxLjY1NjMuMzI4LjQ4OTYuMjEzLjkwMzYuNTE1IDEuMjQyMi45MDYuMzM4NS4zODUuNTk2My44NDEuNzczNCAxLjM2Ny4xNzcxLjUyMS4yNjU2IDEuMDg2LjI2NTYgMS42OTZ2LjE3OWMwIC42MS0uMDg4NSAxLjE3NS0uMjY1NiAxLjY5NS0uMTc3MS41MjEtLjQzNDkuOTc3LS43NzM0IDEuMzY4LS4zMzg2LjM4NS0uNzUuNjg3LTEuMjM0NC45MDYtLjQ4NDQuMjEzLTEuMDMzOS4zMi0xLjY0ODQuMzItLjYxOTggMC0xLjE3NDUtLjEwNy0xLjY2NDEtLjMyLS40ODQ0LS4yMTktLjg5NTgtLjUyMS0xLjIzNDQtLjkwNi0uMzM4NS0uMzkxLS41OTYzLS44NDctLjc3MzQtMS4zNjgtLjE3NzEtLjUyLS4yNjU2LTEuMDg1LS4yNjU2LTEuNjk1Wm0xLjg4MjgtLjE3OXYuMTc5YzAgLjM4LjAzOS43NC4xMTcyIDEuMDc4LjA3ODEuMzM5LjIwMDUuNjM2LjM2NzIuODkxLjE2NjYuMjU1LjM4MDIuNDU2LjY0MDYuNjAyLjI2MDQuMTQ1LjU3MDMuMjE4LjkyOTcuMjE4LjM0ODkgMCAuNjUxLS4wNzMuOTA2Mi0uMjE4LjI2MDQtLjE0Ni40NzQtLjM0Ny42NDA2LS42MDIuMTY2Ny0uMjU1LjI4OTEtLjU1Mi4zNjcyLS44OTEuMDgzNC0uMzM4LjEyNS0uNjk4LjEyNS0xLjA3OHYtLjE3OWMwLS4zNzYtLjA0MTYtLjczLS4xMjUtMS4wNjMtLjA3ODEtLjMzOS0uMjAzMS0uNjM4LS4zNzUtLjg5OC0uMTY2Ni0uMjYxLS4zODAyLS40NjQtLjY0MDYtLjYxLS4yNTUyLS4xNTEtLjU1OTktLjIyNi0uOTE0MS0uMjI2LS4zNTQxIDAtLjY2MTQuMDc1LS45MjE4LjIyNi0uMjU1Mi4xNDYtLjQ2NjIuMzQ5LS42MzI4LjYxLS4xNjY3LjI2LS4yODkxLjU1OS0uMzY3Mi44OTgtLjA3ODIuMzMzLS4xMTcyLjY4Ny0uMTE3MiAxLjA2M1ptMTIuODQwNiAyLjMydi02LjQ2MWgxLjg5MVYxMzNoLTEuNzgybC0uMTA5LTEuOTkyWm0uMjY2LTEuNzU4LjYzMi0uMDE2YzAgLjU2OC0uMDYyIDEuMDkyLS4xODcgMS41NzEtLjEyNS40NzQtLjMxOC44ODgtLjU3OCAxLjI0Mi0uMjYxLjM0OS0uNTk0LjYyMi0xIC44Mi0uNDA2LjE5My0uODkzLjI4OS0xLjQ2MS4yODktLjQxMiAwLS43ODktLjA2LTEuMTMzLS4xNzktLjM0NC0uMTItLjY0MS0uMzA1LS44OTA2LS41NTUtLjI0NDgtLjI1LS40MzQ5LS41NzYtLjU3MDMtLjk3Ny0uMTM1NC0uNDAxLS4yMDMxLS44OC0uMjAzMS0xLjQzN3YtNS40NjFoMS44ODN2NS40NzZjMCAuMzA4LjAzNi41NjYuMTA5Ljc3NC4wNzMuMjAzLjE3Mi4zNjcuMjk3LjQ5MnMuMjcxLjIxNC40MzguMjY2Yy4xNjYuMDUyLjM0My4wNzguNTMxLjA3OC41MzYgMCAuOTU4LS4xMDQgMS4yNjUtLjMxMy4zMTMtLjIxMy41MzQtLjUuNjY0LS44NTkuMTM2LS4zNTkuMjA0LS43NjMuMjA0LTEuMjExWm01LjY0NS0zLjA5NFYxMzNoLTEuODgzdi04LjQ1M2gxLjc5N2wuMDg2IDEuNjA5Wm0yLjU4Ni0xLjY2NC0uMDE2IDEuNzVhMy43NTc0IDMuNzU3NCAwIDAgMC0uMzc1LS4wNDdjLS4xMy0uMDEtLjI2LS4wMTUtLjM5LS4wMTUtLjMyMyAwLS42MDcuMDQ3LS44NTIuMTQtLjI0NS4wODktLjQ1LjIxOS0uNjE3LjM5MS0uMTYyLjE2Ny0uMjg3LjM3LS4zNzUuNjA5LS4wODkuMjQtLjE0MS41MDgtLjE1Ni44MDVsLS40My4wMzFjMC0uNTMxLjA1Mi0xLjAyMy4xNTYtMS40NzYuMTA0LS40NTMuMjYxLS44NTIuNDY5LTEuMTk2LjIxMy0uMzQzLjQ3OS0uNjEyLjc5Ny0uODA0LjMyMy0uMTkzLjY5NS0uMjg5IDEuMTE3LS4yODkuMTE1IDAgLjIzNy4wMS4zNjcuMDMxLjEzNi4wMjEuMjM3LjA0NC4zMDUuMDdabTQuNjc2IDcuMTY0Yy4zMDggMCAuNTg0LS4wNi44MjktLjE3OS4yNS0uMTI1LjQ1LS4yOTcuNjAxLS41MTYuMTU2LS4yMTkuMjQyLS40NzEuMjU4LS43NThoMS43NzNjLS4wMS41NDctLjE3MSAxLjA0NC0uNDg0IDEuNDkyLS4zMTIuNDQ4LS43MjcuODA1LTEuMjQyIDEuMDcxLS41MTYuMjYtMS4wODYuMzktMS43MTEuMzktLjY0NiAwLTEuMjA4LS4xMDktMS42ODgtLjMyOC0uNDc5LS4yMjQtLjg3Ny0uNTMxLTEuMTk1LS45MjItLjMxOC0uMzktLjU1Ny0uODQxLS43MTktMS4zNTEtLjE1Ni0uNTExLS4yMzQtMS4wNTgtLjIzNC0xLjY0MXYtLjI3M2MwLS41ODQuMDc4LTEuMTMxLjIzNC0xLjY0MS4xNjItLjUxNi40MDEtLjk2OS43MTktMS4zNTkuMzE4LS4zOTEuNzE2LS42OTYgMS4xOTUtLjkxNC40OC0uMjI0IDEuMDM5LS4zMzYgMS42OC0uMzM2LjY3NyAwIDEuMjcxLjEzNSAxLjc4MS40MDYuNTExLjI2NS45MTIuNjM4IDEuMjAzIDEuMTE3LjI5Ny40NzQuNDUxIDEuMDI2LjQ2MSAxLjY1NmgtMS43NzNjLS4wMTYtLjMxMi0uMDk0LS41OTMtLjIzNC0uODQzLS4xMzYtLjI1Ni0uMzI5LS40NTktLjU3OS0uNjEtLjI0NC0uMTUxLS41MzktLjIyNi0uODgyLS4yMjYtLjM4MSAwLS42OTYuMDc4LS45NDYuMjM0LS4yNS4xNTEtLjQ0NS4zNTktLjU4Ni42MjUtLjE0LjI2LS4yNDIuNTU1LS4zMDQuODgzLS4wNTguMzIzLS4wODYuNjU5LS4wODYgMS4wMDh2LjI3M2MwIC4zNDkuMDI4LjY4OC4wODYgMS4wMTYuMDU3LjMyOC4xNTYuNjIyLjI5Ny44ODIuMTQ1LjI1Ni4zNDMuNDYxLjU5My42MTguMjUuMTUxLjU2OC4yMjYuOTUzLjIyNlptOC44MzMgMS41Yy0uNjI1IDAtMS4xOS0uMTAxLTEuNjk1LS4zMDQtLjUtLjIwOS0uOTI3LS40OTgtMS4yODEtLjg2OC0uMzQ5LS4zNjktLjYxNy0uODA0LS44MDUtMS4zMDQtLjE4Ny0uNS0uMjgxLTEuMDM5LS4yODEtMS42MTh2LS4zMTJjMC0uNjYxLjA5Ni0xLjI2LjI4OS0xLjc5Ny4xOTMtLjUzNi40NjEtLjk5NS44MDUtMS4zNzUuMzQzLS4zODUuNzUtLjY4IDEuMjE4LS44ODMuNDY5LS4yMDMuOTc3LS4zMDQgMS41MjQtLjMwNC42MDQgMCAxLjEzMy4xMDEgMS41ODYuMzA0LjQ1My4yMDMuODI4LjQ5IDEuMTI1Ljg2LjMwMi4zNjQuNTI2Ljc5OS42NzIgMS4zMDQuMTUxLjUwNi4yMjYgMS4wNjMuMjI2IDEuNjcydi44MDVoLTYuNTMxdi0xLjM1Mmg0LjY3MnYtLjE0OGMtLjAxMS0uMzM5LS4wNzgtLjY1Ni0uMjAzLS45NTMtLjEyLS4yOTctLjMwNS0uNTM3LS41NTUtLjcxOS0uMjUtLjE4Mi0uNTgzLS4yNzMtMS0uMjczLS4zMTMgMC0uNTkxLjA2Ny0uODM2LjIwMy0uMjQuMTMtLjQ0LjMyLS42MDIuNTctLjE2MS4yNS0uMjg2LjU1Mi0uMzc1LjkwNi0uMDgzLjM0OS0uMTI1Ljc0Mi0uMTI1IDEuMTh2LjMxMmMwIC4zNy4wNS43MTQuMTQ5IDEuMDMyLjEwNC4zMTIuMjU1LjU4Ni40NTMuODIuMTk4LjIzNC40MzcuNDE5LjcxOS41NTUuMjgxLjEzLjYwMS4xOTUuOTYxLjE5NS40NTMgMCAuODU2LS4wOTEgMS4yMTEtLjI3My4zNTQtLjE4My42NjEtLjQ0LjkyMS0uNzc0bC45OTMuOTYxYy0uMTgzLjI2Ni0uNDIuNTIxLS43MTEuNzY2LS4yOTIuMjM5LS42NDkuNDM1LTEuMDcxLjU4Ni0uNDE2LjE1MS0uOTAxLjIyNi0xLjQ1My4yMjZabTkuNzk0LTIuNDQ1YzAtLjE4OC0uMDQ3LS4zNTctLjE0MS0uNTA4LS4wOTMtLjE1Ni0uMjczLS4yOTctLjUzOS0uNDIyLS4yNi0uMTI1LS42NDYtLjIzOS0xLjE1Ni0uMzQzLS40NDgtLjA5OS0uODU5LS4yMTctMS4yMzQtLjM1Mi0uMzctLjE0MS0uNjg4LS4zMS0uOTUzLS41MDgtLjI2Ni0uMTk4LS40NzItLjQzMi0uNjE4LS43MDMtLjE0NS0uMjcxLS4yMTgtLjU4My0uMjE4LS45MzcgMC0uMzQ0LjA3NS0uNjcuMjI2LS45NzcuMTUxLS4zMDcuMzY3LS41NzguNjQ5LS44MTMuMjgxLS4yMzQuNjIyLS40MTkgMS4wMjMtLjU1NC40MDYtLjEzNi44NTktLjIwMyAxLjM1OS0uMjAzLjcwOSAwIDEuMzE2LjExOSAxLjgyMS4zNTkuNTEuMjM0LjkwMS41NTUgMS4xNzIuOTYxLjI3LjQwMS40MDYuODU0LjQwNiAxLjM1OWgtMS44ODNjMC0uMjI0LS4wNTctLjQzMi0uMTcyLS42MjUtLjEwOS0uMTk4LS4yNzYtLjM1Ni0uNS0uNDc2LS4yMjQtLjEyNS0uNTA1LS4xODgtLjg0NC0uMTg4LS4zMjIgMC0uNTkxLjA1Mi0uODA0LjE1Ny0uMjA5LjA5OC0uMzY1LjIyOS0uNDY5LjM5LS4wOTkuMTYyLS4xNDguMzM5LS4xNDguNTMxIDAgLjE0MS4wMjYuMjY5LjA3OC4zODMuMDU3LjExLjE1MS4yMTEuMjgxLjMwNS4xMy4wODguMzA3LjE3Mi41MzEuMjUuMjI5LjA3OC41MTYuMTU0Ljg2LjIyNi42NDUuMTM2IDEuMi4zMSAxLjY2NC41MjQuNDY4LjIwOC44MjguNDc5IDEuMDc4LjgxMi4yNS4zMjkuMzc1Ljc0NS4zNzUgMS4yNSAwIC4zNzUtLjA4MS43MTktLjI0MiAxLjAzMi0uMTU3LjMwNy0uMzg2LjU3NS0uNjg4LjgwNC0uMzAyLjIyNC0uNjY0LjM5OS0xLjA4Ni41MjQtLjQxNy4xMjUtLjg4NS4xODctMS40MDYuMTg3LS43NjYgMC0xLjQxNC0uMTM1LTEuOTQ1LS40MDYtLjUzMi0uMjc2LS45MzUtLjYyOC0xLjIxMS0xLjA1NS0uMjcxLS40MzItLjQwNy0uODgtLjQwNy0xLjM0M2gxLjgyMWMuMDIxLjM0OS4xMTcuNjI3LjI4OS44MzYuMTc3LjIwMy4zOTYuMzUxLjY1Ni40NDUuMjY2LjA4OC41MzkuMTMzLjgyLjEzMy4zMzkgMCAuNjIzLS4wNDUuODUyLS4xMzMuMjI5LS4wOTQuNDA0LS4yMTkuNTIzLS4zNzUuMTItLjE2Mi4xOC0uMzQ0LjE4LS41NDdaTTYxLjEyNDIgMTQ5Ljg0NGMwLS4xOTktLjAzMTItLjM3NS0uMDkzNy0uNTI4LS4wNTg2LS4xNTYtLjE2NDEtLjI5Ni0uMzE2NC0uNDIxLS4xNDg1LS4xMjUtLjM1NTUtLjI0NS0uNjIxMS0uMzU4LS4yNjE4LS4xMTMtLjU5MzgtLjIyOC0uOTk2MS0uMzQ2LS40MjE5LS4xMjUtLjgwMjgtLjI2My0xLjE0MjYtLjQxNi0uMzM5OC0uMTU2LS42MzA5LS4zMzQtLjg3MzEtLjUzMy0uMjQyMS0uMTk5LS40Mjc3LS40MjgtLjU1NjYtLjY4NS0uMTI4OS0uMjU4LS4xOTM0LS41NTMtLjE5MzQtLjg4NSAwLS4zMzIuMDY4NC0uNjM5LjIwNTEtLjkycy4zMzIxLS41MjUuNTg2LS43MzJjLjI1NzgtLjIxMS41NjQ0LS4zNzUuOTE5OS0uNDkzLjM1NTUtLjExNy43NTE5LS4xNzUgMS4xODk0LS4xNzUuNjQwNyAwIDEuMTgzNi4xMjMgMS42Mjg5LjM2OS40NDkzLjI0Mi43OTExLjU2IDEuMDI1NC45NTUuMjM0NC4zOS4zNTE2LjgwOC4zNTE2IDEuMjU0aC0xLjEyNWMwLS4zMjEtLjA2ODQtLjYwNC0uMjA1MS0uODUtLjEzNjctLjI1LS4zNDM3LS40NDUtLjYyMTEtLjU4Ni0uMjc3My0uMTQ0LS42Mjg5LS4yMTctMS4wNTQ3LS4yMTctLjQwMjMgMC0uNzM0My4wNjEtLjk5NjEuMTgyLS4yNjE3LjEyMS0uNDU3LjI4NS0uNTg1OS40OTItLjEyNS4yMDctLjE4NzUuNDQ0LS4xODc1LjcwOSAwIC4xOC4wMzcxLjM0NC4xMTEzLjQ5Mi4wNzgyLjE0NS4xOTczLjI4LjM1NzUuNDA1LjE2NC4xMjUuMzcxMS4yNC42MjExLjM0NS4yNTM5LjEwNi41NTY2LjIwNy45MDgyLjMwNS40ODQzLjEzNy45MDIzLjI4OSAxLjI1MzkuNDU3LjM1MTUuMTY4LjY0MDYuMzU3Ljg2NzEuNTY4LjIzMDUuMjA3LjQwMDQuNDQ0LjUwOTguNzA5LjExMzMuMjYyLjE2OTkuNTU5LjE2OTkuODkxIDAgLjM0OC0uMDcwMy42NjItLjIxMDkuOTQzLS4xNDA2LjI4Mi0uMzQxOC41MjItLjYwMzUuNzIxLS4yNjE3LjE5OS0uNTc2Mi4zNTQtLjk0MzQuNDYzLS4zNjMzLjEwNS0uNzY5NS4xNTgtMS4yMTg3LjE1OGE0LjIzOCA0LjIzOCAwIDAgMS0xLjE2Ni0uMTY0Yy0uMzc4OS0uMTA5LS43MjQ3LS4yNzMtMS4wMzcyLS40OTItLjMwODUtLjIxOS0uNTU2Ni0uNDg4LS43NDQxLS44MDktLjE4MzYtLjMyNC0uMjc1NC0uNjk5LS4yNzU0LTEuMTI1aDEuMTI1YzAgLjI5My4wNTY3LjU0NS4xNjk5Ljc1Ni4xMTMzLjIwNy4yNjc2LjM3OS40NjI5LjUxNi4xOTkyLjEzNy40MjM5LjIzOC42NzM5LjMwNS4yNTM5LjA2Mi41MTc1LjA5My43OTEuMDkzLjM5NDUgMCAuNzI4NS0uMDU0IDEuMDAxOS0uMTY0LjI3MzUtLjEwOS40ODA1LS4yNjUuNjIxMS0uNDY5LjE0NDYtLjIwMy4yMTY4LS40NDMuMjE2OC0uNzJabTcuOTI4NS0uNTU3aDEuMTI1Yy0uMDU4Ni41MzktLjIxMjkgMS4wMjItLjQ2MjkgMS40NDctLjI1LjQyNi0uNjAzNS43NjQtMS4wNjA1IDEuMDE0LS40NTcuMjQ2LTEuMDI3My4zNjktMS43MTA5LjM2OS0uNSAwLS45NTUxLS4wOTQtMS4zNjUzLS4yODFhMy4wMzc3IDMuMDM3NyAwIDAgMS0xLjA0ODgtLjc5N2MtLjI5My0uMzQ4LS41MTk1LS43NjQtLjY3OTctMS4yNDgtLjE1NjItLjQ4OC0uMjM0NC0xLjAzMS0uMjM0NC0xLjYyOXYtLjg1YzAtLjU5Ny4wNzgyLTEuMTM4LjIzNDQtMS42MjMuMTYwMi0uNDg4LjM4ODctLjkwNi42ODU2LTEuMjUzYTMuMDQ4NiAzLjA0ODYgMCAwIDEgMS4wODM5LS44MDNjLjQyMTktLjE4OC44OTY1LS4yODEgMS40MjM5LS4yODEuNjQ0NSAwIDEuMTg5NC4xMjEgMS42MzQ3LjM2My40NDUzLjI0Mi43OTExLjU3OCAxLjAzNzEgMS4wMDguMjUuNDI1LjQwNDMuOTIuNDYyOSAxLjQ4MmgtMS4xMjVjLS4wNTQ3LS4zOTgtLjE1NjItLjc0LS4zMDQ3LTEuMDI1LS4xNDg0LS4yODktLjM1OTMtLjUxMi0uNjMyOC0uNjY4LS4yNzM0LS4xNTctLjYzMDgtLjIzNS0xLjA3MjItLjIzNS0uMzc4OSAwLS43MTI5LjA3My0xLjAwMi4yMTctLjI4NTEuMTQ1LS41MjU0LjM1LS43MjA3LjYxNS0uMTkxNC4yNjYtLjMzNTkuNTg0LS40MzM2Ljk1NS0uMDk3Ni4zNzItLjE0NjUuNzg0LS4xNDY1IDEuMjM3di44NjFjMCAuNDE4LjA0My44MTEuMTI4OSAxLjE3OC4wODk5LjM2Ny4yMjQ3LjY4OS40MDQzLjk2Ny4xNzk3LjI3Ny40MDgyLjQ5Ni42ODU2LjY1Ni4yNzczLjE1Ni42MDU1LjIzNC45ODQ0LjIzNC40ODA0IDAgLjg2MzItLjA3NiAxLjE0ODQtLjIyOC4yODUyLS4xNTMuNS0uMzcxLjY0NDUtLjY1Ny4xNDg1LS4yODUuMjUzOS0uNjI2LjMxNjQtMS4wMjVabTYuMDI0My01LjA2Mkw3Mi4yNTI3IDE1MmgtMS4xNTQzbDMuMjUyLTguNTMxaC43NDQxbC0uMDE3NS43NTZaTTc3LjQ0NDEgMTUybC0yLjgzLTcuNzc1LS4wMTc2LS43NTZoLjc0NDFMNzguNjA0MyAxNTJoLTEuMTYwMlptLS4xNDY0LTMuMTU4di45MjZoLTQuNzkzdi0uOTI2aDQuNzkzWk04Mi4yNTU1IDE1MmgtMS43ODEzbC4wMTE3LS45MmgxLjc2OTZjLjYwOTMgMCAxLjExNzItLjEyNyAxLjUyMzQtLjM4MS40MDYzLS4yNTguNzEwOS0uNjE3LjkxNDEtMS4wNzguMjA3LS40NjUuMzEwNS0xLjAwOC4zMTA1LTEuNjI5di0uNTIxYzAtLjQ4OS0uMDU4Ni0uOTIyLS4xNzU4LTEuMzAxLS4xMTcyLS4zODMtLjI4OS0uNzA1LS41MTU2LS45NjctLjIyNjYtLjI2NS0uNTAzOS0uNDY3LS44MzItLjYwMy0uMzI0Mi0uMTM3LS42OTczLS4yMDUtMS4xMTkyLS4yMDVoLTEuOTIxOHYtLjkyNmgxLjkyMThjLjU1ODYgMCAxLjA2ODQuMDkzIDEuNTI5My4yODEuNDYxLjE4NC44NTc1LjQ1MSAxLjE4OTUuODAzLjMzNTkuMzQ3LjU5MzcuNzY5Ljc3MzQgMS4yNjUuMTc5Ny40OTMuMjY5NiAxLjA0Ny4yNjk2IDEuNjY0di41MWMwIC42MTctLjA4OTkgMS4xNzQtLjI2OTYgMS42Ny0uMTc5Ny40OTItLjQzOTQuOTEyLS43NzkzIDEuMjYtLjMzNTkuMzQ4LS43NDIyLjYxNS0xLjIxODcuODAzLS40NzI3LjE4My0xLjAwNTkuMjc1LTEuNTk5Ni4yNzVabS0xLjE3NzgtOC41MzFWMTUyaC0xLjEzMDh2LTguNTMxaDEuMTMwOFptOS45NzM1Ljc1Nkw4OC4yMjcgMTUyaC0xLjE1NDNsMy4yNTE5LTguNTMxaC43NDQxbC0uMDE3NS43NTZaTTkzLjQxODQgMTUybC0yLjgzMDEtNy43NzUtLjAxNzYtLjc1NmguNzQ0MUw5NC41Nzg1IDE1MmgtMS4xNjAxWm0tLjE0NjUtMy4xNTh2LjkyNmgtNC43OTN2LS45MjZoNC43OTNabTkuMzUzMSAxLjQ3NmMwLS4xNTYtLjAzNS0uMy0uMTA1LS40MzMtLjA2Ny0uMTM3LS4yMDYtLjI2LS40MTYtLjM2OS0uMjA4LS4xMTQtLjUyLS4yMTEtLjkzOC0uMjkzLS4zNTItLjA3NS0uNjctLjE2Mi0uOTU1LS4yNjQtLjI4MTMtLjEwMi0uNTIxNS0uMjI1LS43MjA4LS4zNjktLjE5NTMtLjE0NS0uMzQ1Ny0uMzE1LS40NTExLS41MS0uMTA1NS0uMTk1LS4xNTgyLS40MjQtLjE1ODItLjY4NSAwLS4yNS4wNTQ2LS40ODcuMTY0LS43MDkuMTEzMy0uMjIzLjI3MTUtLjQyLjQ3NDYtLjU5Mi4yMDcxLS4xNzIuNDU1MS0uMzA3Ljc0NDUtLjQwNS4yODktLjA5Ny42MTEtLjE0Ni45NjYtLjE0Ni41MDggMCAuOTQyLjA5IDEuMzAxLjI2OS4zNi4xOC42MzUuNDIuODI2LjcyMS4xOTIuMjk3LjI4OC42MjcuMjg4Ljk5aC0xLjA4NGMwLS4xNzUtLjA1My0uMzQ1LS4xNTktLjUwOS0uMTAxLS4xNjgtLjI1Mi0uMzA3LS40NTEtLjQxNi0uMTk1LS4xMS0uNDM1LS4xNjQtLjcyMS0uMTY0LS4zIDAtLjU0NC4wNDYtLjczMi4xNC0uMTg0LjA5LS4zMTguMjA1LS40MDQuMzQ2LS4wODIuMTQxLS4xMjMzLjI4OS0uMTIzMy40NDUgMCAuMTE3LjAxOTUuMjIzLjA1ODMuMzE3LjA0My4wODkuMTE3LjE3My4yMjMuMjUyLjEwNS4wNzQuMjU0LjE0NC40NDUuMjExLjE5Mi4wNjYuNDM2LjEzMi43MzMuMTk5LjUxOS4xMTcuOTQ3LjI1OCAxLjI4My40MjIuMzM2LjE2NC41ODYuMzY1Ljc1LjYwMy4xNjQuMjM4LjI0Ni41MjcuMjQ2Ljg2NyAwIC4yNzgtLjA1OS41MzItLjE3Ni43NjItLjExMy4yMzEtLjI3OS40My0uNDk4LjU5OC0uMjE1LjE2NC0uNDczLjI5My0uNzczLjM4Ni0uMjk3LjA5LS42MzEuMTM1LTEuMDAyLjEzNS0uNTU5IDAtMS4wMzEtLjA5OS0xLjQxODItLjI5OS0uMzg2Ny0uMTk5LS42Nzk3LS40NTctLjg3ODktLjc3My0uMTk5Mi0uMzE2LS4yOTg4LS42NS0uMjk4OC0xLjAwMmgxLjA4OThjLjAxNTYuMjk3LjEwMTYuNTMzLjI1ODEuNzA5LjE1Ni4xNzIuMzQ3LjI5NS41NzQuMzY5LjIyNi4wNy40NTEuMTA2LjY3NC4xMDYuMjk3IDAgLjU0NS0uMDM5Ljc0NC0uMTE4LjIwMy0uMDc4LjM1Ny0uMTg1LjQ2My0uMzIyLjEwNS0uMTM3LjE1OC0uMjkzLjE1OC0uNDY5Wm00LjQ4OSAxLjAyNiAxLjc2NC01LjY4NGgxLjE2bC0yLjU0MyA3LjMxOWMtLjA1OS4xNTYtLjEzNy4zMjQtLjIzNC41MDMtLjA5NC4xODQtLjIxNS4zNTgtLjM2NC41MjItLjE0OC4xNjQtLjMyOC4yOTctLjUzOS4zOTgtLjIwNy4xMDYtLjQ1NS4xNTktLjc0NC4xNTktLjA4NiAwLS4xOTUtLjAxMi0uMzI4LS4wMzYtLjEzMy0uMDIzLS4yMjctLjA0My0uMjgxLS4wNThsLS4wMDYtLjg3OWMuMDMxLjAwNC4wOC4wMDguMTQ2LjAxMi4wNzEuMDA3LjExOS4wMTEuMTQ3LjAxMS4yNDYgMCAuNDU1LS4wMzMuNjI3LS4wOTkuMTcyLS4wNjMuMzE2LS4xNy40MzMtLjMyMy4xMjEtLjE0OC4yMjUtLjM1My4zMTEtLjYxNWwuNDUxLTEuMjNabS0xLjI5NS01LjY4NCAxLjY0NyA0LjkyMi4yODEgMS4xNDMtLjc3OS4zOTgtMi4zMzItNi40NjNoMS4xODNabTYuNDc2IDEuMjZWMTUyaC0xLjA5di02LjM0aDEuMDMxbC4wNTkgMS4yNlptLS4yMjMgMS42Ny0uNTA0LS4wMThjLjAwNC0uNDMzLjA2MS0uODM0LjE3LTEuMjAxLjEwOS0uMzcxLjI3MS0uNjkzLjQ4Ni0uOTY3LjIxNS0uMjczLjQ4My0uNDg0LjgwMy0uNjMzLjMyLS4xNTIuNjkxLS4yMjggMS4xMTMtLjIyOC4yOTcgMCAuNTcxLjA0My44MjEuMTI5LjI1LjA4Mi40NjYuMjEzLjY1LjM5Mi4xODQuMTguMzI2LjQxMS40MjguNjkyLjEwMS4yODEuMTUyLjYyMS4xNTIgMS4wMTlWMTUyaC0xLjA4NHYtNC4xNzJjMC0uMzMyLS4wNTctLjU5OC0uMTctLjc5Ny0uMTA5LS4xOTktLjI2Ni0uMzQzLS40NjktLjQzMy0uMjAzLS4wOTQtLjQ0MS0uMTQxLS43MTQtLjE0MS0uMzIxIDAtLjU4OC4wNTctLjgwMy4xNy0uMjE1LjExMy0uMzg3LjI2OS0uNTE2LjQ2OS0uMTI5LjE5OS0uMjIzLjQyNy0uMjgxLjY4NS0uMDU1LjI1NC0uMDgyLjUyNC0uMDgyLjgwOVptNC4xMDctLjU5OC0uNzI2LjIyM2MuMDA0LS4zNDguMDYtLjY4Mi4xNy0xLjAwMi4xMTMtLjMyLjI3NS0uNjA2LjQ4Ni0uODU2LjIxNS0uMjUuNDc4LS40NDcuNzkxLS41OTEuMzEyLS4xNDkuNjctLjIyMyAxLjA3Mi0uMjIzLjM0IDAgLjY0MS4wNDUuOTAzLjEzNS4yNjUuMDkuNDg4LjIyOC42NjguNDE2LjE4My4xODMuMzIyLjQyLjQxNi43MDkuMDkzLjI4OS4xNC42MzMuMTQgMS4wMzFWMTUyaC0xLjA5di00LjE3OGMwLS4zNTUtLjA1Ni0uNjMxLS4xNy0uODI2LS4xMDktLjE5OS0uMjY1LS4zMzgtLjQ2OC0uNDE2LS4yLS4wODItLjQzOC0uMTIzLS43MTUtLjEyMy0uMjM4IDAtLjQ0OS4wNDEtLjYzMy4xMjMtLjE4NC4wODItLjMzOC4xOTUtLjQ2My4zNGExLjQ4NSAxLjQ4NSAwIDAgMC0uMjg3LjQ4NmMtLjA2Mi4xODQtLjA5NC4zNzktLjA5NC41ODZabTUuNzU1LTQuOTkyaDEuMDl2Ny43N2wtLjA5NCAxLjIzaC0uOTk2di05Wm01LjM3MyA1Ljc3N3YuMTIzYzAgLjQ2MS0uMDU1Ljg4OS0uMTY0IDEuMjg0LS4xMDkuMzktLjI3LjczLS40OCAxLjAxOS0uMjExLjI4OS0uNDY5LjUxNC0uNzc0LjY3NC0uMzA1LjE2LS42NTQuMjQtMS4wNDkuMjQtLjQwMiAwLS43NTYtLjA2OC0xLjA2LS4yMDVhMi4wOTM0IDIuMDkzNCAwIDAgMS0uNzYyLS42MDNjLS4yMDctLjI2Mi0uMzczLS41NzktLjQ5OC0uOTUtLjEyMS0uMzcxLS4yMDUtLjc4OS0uMjUyLTEuMjU0di0uNTM5Yy4wNDctLjQ2OC4xMzEtLjg4OC4yNTItMS4yNTkuMTI1LS4zNzEuMjkxLS42ODguNDk4LS45NS4yMDctLjI2NS40NjEtLjQ2Ni43NjItLjYwMy4zLS4xNDEuNjUtLjIxMSAxLjA0OS0uMjExLjM5OCAwIC43NTEuMDc4IDEuMDYuMjM0LjMwOS4xNTMuNTY2LjM3MS43NzQuNjU3LjIxLjI4NS4zNzEuNjI3LjQ4IDEuMDI1LjEwOS4zOTUuMTY0LjgzNC4xNjQgMS4zMThabS0xLjA5LjEyM3YtLjEyM2MwLS4zMTYtLjAyOS0uNjEzLS4wODgtLjg5LS4wNTgtLjI4Mi0uMTUyLS41MjgtLjI4MS0uNzM5LS4xMjktLjIxNC0uMjk5LS4zODItLjUxLS41MDMtLjIxMS0uMTI1LS40Ny0uMTg4LS43NzktLjE4OC0uMjczIDAtLjUxMi4wNDctLjcxNS4xNDEtLjE5OS4wOTMtLjM2OS4yMi0uNTEuMzgxLS4xNC4xNTYtLjI1NS4zMzUtLjM0NS41MzktLjA4Ni4xOTktLjE1MS40MDYtLjE5NC42MjF2MS40MTJjLjA2My4yNzMuMTY0LjUzNy4zMDUuNzkxLjE0NS4yNS4zMzYuNDU1LjU3NC42MTUuMjQyLjE2LjU0MS4yNC44OTcuMjQuMjkzIDAgLjU0My0uMDU4Ljc1LS4xNzYuMjExLS4xMjEuMzgxLS4yODcuNTA5LS40OTguMTMzLS4yMTEuMjMxLS40NTUuMjkzLS43MzIuMDYzLS4yNzcuMDk0LS41NzQuMDk0LS44OTFabTIuMzc0IDB2LS4xMzRjMC0uNDU3LjA2Ni0uODgxLjE5OS0xLjI3Mi4xMzMtLjM5NC4zMjQtLjczNi41NzQtMS4wMjUuMjUtLjI5My41NTMtLjUyLjkwOS0uNjguMzU1LS4xNjQuNzU0LS4yNDYgMS4xOTUtLjI0Ni40NDUgMCAuODQ2LjA4MiAxLjIwMS4yNDYuMzYuMTYuNjY0LjM4Ny45MTQuNjguMjU0LjI4OS40NDcuNjMxLjU4IDEuMDI1LjEzMy4zOTEuMi44MTUuMiAxLjI3MnYuMTM0YzAgLjQ1Ny0uMDY3Ljg4MS0uMiAxLjI3Mi0uMTMzLjM5LS4zMjYuNzMyLS41OCAxLjAyNS0uMjUuMjg5LS41NTMuNTE2LS45MDguNjgtLjM1Mi4xNi0uNzUuMjQtMS4xOTUuMjQtLjQ0NiAwLS44NDYtLjA4LTEuMjAxLS4yNC0uMzU2LS4xNjQtLjY2MS0uMzkxLS45MTUtLjY4LS4yNS0uMjkzLS40NDEtLjYzNS0uNTc0LTEuMDI1LS4xMzMtLjM5MS0uMTk5LS44MTUtLjE5OS0xLjI3MlptMS4wODQtLjEzNHYuMTM0YzAgLjMxNy4wMzcuNjE2LjExMS44OTcuMDc1LjI3Ny4xODYuNTIzLjMzNC43MzguMTUzLjIxNS4zNDIuMzg1LjU2OS41MS4yMjYuMTIxLjQ5LjE4Mi43OTEuMTgyLjI5NyAwIC41NTYtLjA2MS43NzktLjE4Mi4yMjctLjEyNS40MTQtLjI5NS41NjItLjUxLjE0OS0uMjE1LjI2LS40NjEuMzM0LS43MzguMDc5LS4yODEuMTE4LS41OC4xMTgtLjg5N3YtLjEzNGMwLS4zMTMtLjAzOS0uNjA4LS4xMTgtLjg4NS0uMDc0LS4yODEtLjE4Ny0uNTI5LS4zMzktLjc0NC0uMTQ5LS4yMTktLjMzNi0uMzkxLS41NjMtLjUxNi0uMjIzLS4xMjUtLjQ4NC0uMTg3LS43ODUtLjE4Ny0uMjk3IDAtLjU1OS4wNjItLjc4NS4xODctLjIyMy4xMjUtLjQxLjI5Ny0uNTYzLjUxNi0uMTQ4LjIxNS0uMjU5LjQ2My0uMzM0Ljc0NC0uMDc0LjI3Ny0uMTExLjU3Mi0uMTExLjg4NVpNMTM3LjEgMTQzdjloLTEuMDl2LTloMS4wOVptNS42MzEgNy4zMThjMC0uMTU2LS4wMzUtLjMtLjEwNS0uNDMzLS4wNjctLjEzNy0uMjA1LS4yNi0uNDE2LS4zNjktLjIwNy0uMTE0LS41Mi0uMjExLS45MzgtLjI5My0uMzUxLS4wNzUtLjY3LS4xNjItLjk1NS0uMjY0LS4yODEtLjEwMi0uNTIxLS4yMjUtLjcyMS0uMzY5LS4xOTUtLjE0NS0uMzQ1LS4zMTUtLjQ1MS0uNTEtLjEwNS0uMTk1LS4xNTgtLjQyNC0uMTU4LS42ODUgMC0uMjUuMDU1LS40ODcuMTY0LS43MDkuMTEzLS4yMjMuMjcyLS40Mi40NzUtLjU5Mi4yMDctLjE3Mi40NTUtLjMwNy43NDQtLjQwNS4yODktLjA5Ny42MTEtLjE0Ni45NjctLjE0Ni41MDggMCAuOTQxLjA5IDEuMy4yNjkuMzYuMTguNjM1LjQyLjgyNy43MjEuMTkxLjI5Ny4yODcuNjI3LjI4Ny45OWgtMS4wODRjMC0uMTc1LS4wNTMtLjM0NS0uMTU4LS41MDktLjEwMi0uMTY4LS4yNTItLjMwNy0uNDUyLS40MTYtLjE5NS0uMTEtLjQzNS0uMTY0LS43Mi0uMTY0LS4zMDEgMC0uNTQ1LjA0Ni0uNzMzLjE0LS4xODMuMDktLjMxOC4yMDUtLjQwNC4zNDYtLjA4Mi4xNDEtLjEyMy4yODktLjEyMy40NDUgMCAuMTE3LjAxOS4yMjMuMDU5LjMxNy4wNDMuMDg5LjExNy4xNzMuMjIyLjI1Mi4xMDYuMDc0LjI1NC4xNDQuNDQ2LjIxMS4xOTEuMDY2LjQzNS4xMzIuNzMyLjE5OS41MTkuMTE3Ljk0Ny4yNTggMS4yODMuNDIyLjMzNi4xNjQuNTg2LjM2NS43NS42MDMuMTY0LjIzOC4yNDYuNTI3LjI0Ni44NjcgMCAuMjc4LS4wNTguNTMyLS4xNzYuNzYyLS4xMTMuMjMxLS4yNzkuNDMtLjQ5OC41OTgtLjIxNC4xNjQtLjQ3Mi4yOTMtLjc3My4zODYtLjI5Ny4wOS0uNjMxLjEzNS0xLjAwMi4xMzUtLjU1OSAwLTEuMDMxLS4wOTktMS40MTgtLjI5OS0uMzg3LS4xOTktLjY4LS40NTctLjg3OS0uNzczLS4xOTktLjMxNi0uMjk5LS42NS0uMjk5LTEuMDAyaDEuMDljLjAxNi4yOTcuMTAyLjUzMy4yNTguNzA5LjE1Ni4xNzIuMzQ4LjI5NS41NzQuMzY5LjIyNy4wNy40NTEuMTA2LjY3NC4xMDYuMjk3IDAgLjU0NS0uMDM5Ljc0NC0uMTE4LjIwMy0uMDc4LjM1OC0uMTg1LjQ2My0uMzIyLjEwNi0uMTM3LjE1OC0uMjkzLjE1OC0uNDY5WiIgZmlsbD0iIzMwNTY4MCIgZmlsbC1vcGFjaXR5PSIuOCIvPjwvc3ZnPg==", "description": "Bundle with SCADA symbols", "order": 9200, "name": "SCADA symbols" diff --git a/application/src/main/data/json/system/widget_types/scada_symbol.json b/application/src/main/data/json/system/widget_types/scada_symbol.json index 61ef5bb529..bdcdd1674d 100644 --- a/application/src/main/data/json/system/widget_types/scada_symbol.json +++ b/application/src/main/data/json/system/widget_types/scada_symbol.json @@ -3,7 +3,7 @@ "name": "SCADA symbol", "deprecated": false, "scada": true, - "image": "tb-image:bmV3X3NjYWRhX3N5bWJvbHNfc3lzdGVtX3dpZGdldF9pbWFnZS5wbmc=:Ik5ldyBTQ0FEQSBzeW1ib2wiIHN5c3RlbSB3aWRnZXQgaW1hZ2U=:SU1BR0U=;data:image/png;base64,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", + "image": "tb-image:bmV3X3NjYWRhX3N5bWJvbHNfc3lzdGVtX3dpZGdldF9pbWFnZV8oMSkuc3Zn:Ik5ldyBTQ0FEQSBzeW1ib2wiIHN5c3RlbSB3aWRnZXQgaW1hZ2U=:SU1BR0U=;data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE2MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBjbGlwLXBhdGg9InVybCgjYSkiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjMzA1NjgwIiBmaWxsLW9wYWNpdHk9Ii42Ij48cGF0aCBkPSJtMTQ3LjE2MyA0OC43NTM3LTE0LjcxOC0xNS4zODU1Yy0xLjIxMy0xLjI2MTQtMi42OTMtMi4xOTYtNC4zNC0yLjczOTYtNS4wNzUtNi41NDc1LTExLjE5OS0xMC42Nzc3LTIwLjEzNC0xMC42Nzc3LTguNjkwNiAwLTE2LjQzMDMgMy42MjQxLTIxLjUzMDMgMTAuMzI4SDcyLjQ0NzRjLTUuNTYzMS4wMDA1LTEwLjE1NyA0LjM2Ny0xMC4xNTcgOS45MzA3djM5Ljc5MDVoNS4wMjhWNDAuMjA5NmMwLTIuNzk1NSAyLjMzMzUtNC45MDIyIDUuMTI5LTQuOTAyMmgxMC43MjU3Yy0xLjkxMTIgMy4zNTE5LTMuMDA1NiA3Ljg0MTktMy4wMDU2IDEyLjM1ODZ2My44NDI1aC04LjM2MmMtLjY1MDggMC0xLjIzOC4yNjI1LTEuNDg4My44NjMxLS4yNTAyLjYwMDYtLjExNTYgMS4yMjg1LjM0MiAxLjY5MTFsMjIuNDE3MyAyMi42MjQ1Yy4zMjM0LjMyNjkuNzY0OC40OTUgMS4yMjQ2LjQ5NS40NTk3IDAgLjkwMTEtLjE5MjIgMS4yMjQ1LS41MTlsMjIuMjg4NC0yMi41MzA3Yy40NzktLjQ4NDQuNjIxLTEuMDgyNy4zNTgtMS43MTIzLS4yNjMtLjYyODUtLjg3Ny0uOTExNy0xLjU1OS0uOTExN0gxMDguMVY0Ny42NjZjMC00Ljk3MzIgMi40ODYtOS41NjUzIDUuODk1LTEyLjM1ODZoOS4xMjNjMS45ODEuNTU4NiAzLjQxOCAyLjA3MzcgMy40MTggNC4yMDIydjEwLjgxMTdjMCAyLjkwMTcgMi4zODYgNS42NTY0IDUuMjg3IDUuNjU2NGg4Ljg5OWMyLjUwMiAwIDQuMzg5IDEuODI2MyA0LjM4OSA0LjMyNjlsLS4xMzktLjIwOVYxMzAuMDVjMCAyLjc5NS0yLjAzMiA1LjI1Ny00LjgyNyA1LjI1N0g3Mi40NDc0Yy0yLjc5NTUgMC01LjEyOS0yLjQ2MS01LjEyOS01LjI1N3YtMi41NjRoLTUuMDI4djIuNTY0YzAgNS41NjQgNC41OTM5IDEwLjI4NSAxMC4xNTcgMTAuMjg1aDY3LjY5NzZjNS41NjMgMCA5Ljg1NS00LjcyMSA5Ljg1NS0xMC4yODVWNTYuMDg3OGMwLTIuNzQ4Ni0uOTMyLTUuMzUzMS0yLjgzNy03LjMzNDFaIi8+PHBhdGggZD0iTTEyNy42NTQgODguMTQ5NmMwLTEuNzI0LTEuMzk4LTMuMTIxOC0zLjEyMi0zLjEyMThINTMuMTIxN2MtMS43MjQgMC0zLjEyMTggMS4zOTc4LTMuMTIxOCAzLjEyMTh2MzEuNzQ0NGMwIDEuNzI0IDEuMzk3OCAzLjEyMiAzLjEyMTggMy4xMjJoNzEuNDEwM2MxLjcyNCAwIDMuMTIyLTEuMzk4IDMuMTIyLTMuMTIyVjg4LjE0OTZaTTc2LjEzNjMgMTExLjc1NWMtLjQxMjkuOTE0LTEuMDI3NCAxLjcwMi0xLjg0MzYgMi4zNjYtLjgxNTcuNjYzLTEuODI3NCAxLjE3OS0zLjAzNDcgMS41NDktMS4yMDY3LjM3LTIuNjA1LjU1NS00LjE5MjcuNTU1LTEuMjgzOCAwLTIuNTI4NS0uMTU4LTMuNzM1OC0uNDczLTEuMjA3Mi0uMzE1LTIuMjczMS0uODEtMy4xOTc3LTEuNDg1LS45MjUyLS42NzQtMS42NTkyLTEuNTUyLTIuMjAyMy0yLjU5Ni0uNTQ0MS0xLjA0NC0uODA1LTIuMDYyLS43ODMyLTMuNzM4aDQuOTU5OGMwIDEuMTE3LjE0MTMgMS40NjUuNDI0IDIuMDA5LjI4MjcuNTQ0LjY1ODEuOTk0IDEuMTI2MyAxLjMzMS40Njc2LjMzOCAxLjAxNjIuNTkyIDEuNjQ3NC43NTUuNjMwOC4xNjQgMS4yODMzLjI0NyAxLjk1NzYuMjQ3LjQ1NjQgMCAuOTQ2NC0uMDM3IDEuNDY4MS0uMTEzLjUyMjQtLjA3NiAxLjAxMTgtLjIyMiAxLjQ2ODgtLjQ0LjQ1NjQtLjIxOC44MzY4LS41MTcgMS4xNDE5LS44OTcuMzA0NC0uMzguNDU2NC0uODY1LjQ1NjQtMS40NTIgMC0uNjMxLS4yMDExLTEuMTQyLS42MDM0LTEuNTMzLS40MDI4LS4zOTItLjkzMDEtLjcxOC0xLjU4MjYtLjk3OS0uNjUyNi0uMjYxLTEuMzkyMi0uNDktMi4yMTktLjY4Ni0uODI2My0uMTk1LTEuNjY0My0uNDEzLTIuNTEyMy0uNjUyLS44NzA0LS4yMTgtMS43MTg1LS40ODQtMi41NDQ3LS44LS44MjY4LS4zMTUtMS41NjY1LS43MjMtMi4yMTktMS4yMjMtLjY1MjUtLjUtMS4xODA1LTEuMTI2LTEuNTgyNy0xLjg3Ni0uNDAyOC0uNzUtLjYwMzQtMS42NTgyLS42MDM0LTIuNzI0MSAwLTEuMTk2MS4yNTU0LTIuMjM1Mi43NjY1LTMuMTE2Mi41MTA2LS44ODEgMS4xNzk0LTEuNjE1MSAyLjAwNjctMi4yMDIyLjgyNjMtLjU4NzIgMS43NjItMS4wMjI0IDIuODA2Mi0xLjMwNTEgMS4wNDM2LS4yODI2IDIuMDg3Ny0uNDI0IDMuMTMxOC0uNDI0IDEuMjE3OSAwIDIuMzg2Ni4xMzYzIDMuNTA3My40MDc4IDEuMTIwMS4yNzIxIDIuMTE1MS43MTI5IDIuOTg1NSAxLjMyMTMuODcwMy42MDg5IDEuNTYwOSAxLjQ4NDkgMi4wNzIgMi40MzEyLjUxMDYuOTQ2NC43NjY1IDIuNDIzNS43NjY1IDMuNTQwOGgtNC45NTkyYy0uMDQzNi0uNTU4Ni0uMTkxMS0xLjM3MDktLjQ0MDItMS44MjczLS4yNTAzLS40NTctLjU4MjctLjg2NDktLjk5NTYtMS4xMjU3LS40MTI4LS4yNjA5LS44ODY2LS40NzA0LTEuNDE5LS41Nzk0LS41MzM1LS4xMDg0LTEuMTE1LS4xNzU0LTEuNzQ1OC0uMTc1NC0uNDEzNCAwLS44MjYyLjAzOC0xLjIzOTYuMTI0Ni0uNDEzNC4wODcxLS43ODg5LjIzNjMtMS4xMjYzLjQ1MzYtLjMzNzQuMjE3OS0uNjE1MS40ODc3LS44MzE4LjgxNDUtLjIxNzkuMzI2My0uMzI2My43Mzg2LS4zMjYzIDEuMjM5MiAwIC40NTY0LjA4NjYuODI2Mi4yNjE1IDEuMTA4OS4xNzM3LjI4MjcuNTE2Mi41NDM1IDEuMDI3OS43ODI1LjUxMDYuMjQgMS4yMTc5LjQ3OSAyLjEyMDcuNzE4LjkwMjIuMjQgMi4wODI2LjU0NCAzLjU0MDIuOTEzLjQzNDYuMDg4IDEuMDM4LjI0NSAxLjgxMDYuNDc0Ljc3MjEuMjI4IDEuNTM4Ni41OTIgMi4zIDEuMDkzLjc2MTUuNSAxLjQxOTYgMS4xNyAxLjk3NDMgMi4wMDcuNTU0Mi44MzguODMxOCAxLjkwOS44MzE4IDMuMjE0LjAwMTIgMS4wNjQtLjIwNjEgMi4wNTQtLjYxODkgMi45NjdabTE0LjQ4NiAzLjk5OWgtNS43NzQ5TDc3LjMxIDkyLjg0OTFoNS4yNTMxbDUuMTg3NyAxNi4yMDA5aC4wNjUzbDUuMjUzMS0xNi4yMDA5aDUuMjg1NWwtNy43MzI0IDIyLjkwNDlabTMwLjMyNzcgMGgtMy4yNDdsLS41MjEtMi42NjhjLS45MTQgMS4xNzUtMS45MjYgMS45ODMtMy4wMzUgMi40NTEtMS4xMS40NjctMi4yMy42OTUtMy4zNjEuNjk1LTEuNzg0IDAtMy4zODgtLjMxNC00LjgxMy0uOTMzLTEuNDI1LS42Mi0yLjYyNi0xLjQ3NS0zLjYwNS0yLjU2My0uOTc5LTEuMDg3LTEuNzMtMi4zNjctMi4yNTEtMy44MzUtLjUyMjYtMS40NjgtLjc4My0zLjA1MS0uNzgzLTQuNzQ4IDAtMS43NC4yNjA5LTMuMzU1Ljc4My00Ljg0NTMuNTIyLTEuNDg5OSAxLjI3Mi0yLjc4OTkgMi4yNTEtMy44OTk0Ljk3OS0xLjEwOTUgMi4xOC0xLjk3OTQgMy42MDUtMi42MTAxIDEuNDI1LS42MzA3IDMuMDI5LS45NDU4IDQuODEzLS45NDU4IDEuMTk2IDAgMi4zNTQuMTc5MyAzLjQ3NS41MzggMS4xMi4zNTkyIDIuMTMxLjg4NjYgMy4wMzQgMS41ODIxLjkwMy42OTY3IDEuNjQ4IDEuNTczOCAyLjIzNiAyLjU5NjcuNTg3IDEuMDIyOS45NDUgMi40MjUxIDEuMDc2IDMuNTQyOGgtNC44OTRjLS4zMDUtMS4xMTc3LS44OTItMi4zMDMyLTEuNzYyLTIuOTU1Ny0uODctLjY1MjUtMS45MjUtLjk4ODItMy4xNjQtLjk4ODItMS4xNTQgMC0yLjEzMi4yMTktMi45MzcuNjY0Mi0uODA1LjQ0NjQtMS40NTggMS4wNDE5LTEuOTU4IDEuNzkyMnMtLjg2NSAxLjYwMzUtMS4wOTMgMi41NjA1Yy0uMjI5Ljk1Ny0uMzQzIDEuOTQ2LS4zNDMgMi45NjggMCAuOTc5LjExNCAxLjkzMS4zNDMgMi44NTUuMjI4LjkyNS41OTMgMS43NTcgMS4wOTMgMi40OTYuNS43MzkgMS4xNTIgMS4zMzIgMS45NTggMS43NzguODA0LjQ0NiAxLjc4My42NjkgMi45MzcuNjY5IDEuNjk2IDAgMy4wMDYtLjIwNiAzLjkzMS0xLjA2NS45MjQtLjg1OSAxLjQ2Mi0yLjM5NSAxLjYxNS0zLjUxMmgtNS40Mzl2LTMuOTExaDEwLjA1NnYxMi4yOTFaIi8+PC9nPjxkZWZzPjxjbGlwUGF0aCBpZD0iYSI+PHBhdGggZmlsbD0iI2ZmZiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTAgMTkuNjY0OCkiIGQ9Ik0wIDBoMTAwdjEyMC42N0gweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==", "description": "", "descriptor": { "type": "rpc", From 24a3375848cf3875a3e1a94b96c5ceb12ccf0b5c Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Tue, 10 Sep 2024 11:20:52 +0300 Subject: [PATCH 56/80] UI: Refactoring --- .../widget/lib/scada/scada-symbol.models.ts | 13 +++++++++++-- .../home/pages/admin/admin-routing.module.ts | 3 +-- .../components/image/image-gallery.component.ts | 6 +----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts index bb6cc17869..733e7078dd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts @@ -255,8 +255,17 @@ const parseScadaSymbolMetadataFromDom = (svgDoc: Document): ScadaSymbolMetadata if (elements.length) { return JSON.parse(elements[0].textContent); } else { - const viewBox = svgDoc.getElementsByTagName('svg')[0].viewBox.baseVal; - return emptyMetadata(viewBox.width, viewBox.height); + const svg = svgDoc.getElementsByTagName('svg')[0]; + let width = null; + let height = null; + if (svg.viewBox.baseVal.width && svg.viewBox.baseVal.height) { + width = svg.viewBox.baseVal.width; + height = svg.viewBox.baseVal.height; + } else if (svg.width.baseVal.value && svg.height.baseVal.value) { + width = svg.width.baseVal.value; + height = svg.height.baseVal.value; + } + return emptyMetadata(width, height); } } catch (_e) { console.error(_e); diff --git a/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts b/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts index b4a4d01326..7d3e9983f8 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts @@ -114,8 +114,7 @@ const routes: Routes = [ data: { auth: [Authority.TENANT_ADMIN, Authority.SYS_ADMIN], title: 'scada.symbols', - imageSubType: ResourceSubType.SCADA_SYMBOL, - editOnRowClick: true + imageSubType: ResourceSubType.SCADA_SYMBOL } }, { diff --git a/ui-ngx/src/app/shared/components/image/image-gallery.component.ts b/ui-ngx/src/app/shared/components/image/image-gallery.component.ts index 419e637f0c..ca24fb55b0 100644 --- a/ui-ngx/src/app/shared/components/image/image-gallery.component.ts +++ b/ui-ngx/src/app/shared/components/image/image-gallery.component.ts @@ -181,8 +181,6 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe return this.imageSubType === ResourceSubType.SCADA_SYMBOL; } - private editOnRowClick = false; - private updateDataSubscription: Subscription; private widgetResize$: ResizeObserver; @@ -219,7 +217,6 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe const routerQueryParams: PageQueryParam = this.route.snapshot.queryParams; if (this.pageMode) { this.imageSubType = this.route.snapshot.data.imageSubType || ResourceSubType.IMAGE; - this.editOnRowClick = this.route.snapshot.data.editOnRowClick || false; if (routerQueryParams.hasOwnProperty('direction') || routerQueryParams.hasOwnProperty('property')) { sortOrder = { @@ -642,9 +639,8 @@ export class ImageGalleryComponent extends PageComponent implements OnInit, OnDe } rowClick($event, image: ImageResourceInfo) { - if (this.editOnRowClick) { + if (this.isScada) { this.editImage($event, image); - } else { if (this.selectionMode) { this.selectImage($event, image); From fb1d99329062afa284e04cb5a37aa9fd32cc6537 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 10 Sep 2024 12:38:06 +0300 Subject: [PATCH 57/80] UI: Refactor widget padding change default value for backward compatibility --- .../lib/cards/value-card-widget.component.ts | 21 +++++------ .../lib/cards/value-card-widget.models.ts | 8 +++-- .../indicator/status-widget.component.html | 4 +-- .../indicator/status-widget.component.scss | 3 +- .../lib/indicator/status-widget.component.ts | 35 +++++++++---------- .../lib/rpc/single-switch-widget.component.ts | 23 +++++------- .../lib/rpc/single-switch-widget.models.ts | 2 +- .../wind-speed-direction-widget.models.ts | 3 +- 8 files changed, 46 insertions(+), 53 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts index d28f62ee57..96ec634362 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.component.ts @@ -37,7 +37,8 @@ import { getLabel, getSingleTsValue, iconStyle, - overlayStyle, resolveCssSize, + overlayStyle, + resolveCssSize, textStyle } from '@shared/models/widget-settings.models'; import { valueCardDefaultSettings, ValueCardLayout, ValueCardWidgetSettings } from './value-card-widget.models'; @@ -48,7 +49,6 @@ import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; const squareLayoutSize = 160; -const squareLayoutPadding = 48; const horizontalLayoutHeight = 80; @Component({ @@ -201,16 +201,13 @@ export class ValueCardWidgetComponent implements OnInit, AfterViewInit, OnDestro } private onResize() { - const paddingLeft = getComputedStyle(this.valueCardPanel.nativeElement).paddingLeft; - const paddingRight = getComputedStyle(this.valueCardPanel.nativeElement).paddingRight; - const paddingTop = getComputedStyle(this.valueCardPanel.nativeElement).paddingTop; - const paddingBottom = getComputedStyle(this.valueCardPanel.nativeElement).paddingBottom; - const pLeft = resolveCssSize(paddingLeft)[0]; - const pRight = resolveCssSize(paddingRight)[0]; - const pTop = resolveCssSize(paddingTop)[0]; - const pBottom = resolveCssSize(paddingBottom)[0]; - const panelWidth = this.valueCardPanel.nativeElement.getBoundingClientRect().width - (pLeft + pRight); - const panelHeight = this.valueCardPanel.nativeElement.getBoundingClientRect().height - (pTop + pBottom); + const computedStyle = getComputedStyle(this.valueCardPanel.nativeElement); + const [pLeft, pRight, pTop, pBottom] = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'] + .map(side => resolveCssSize(computedStyle[side])[0]); + + const widgetBoundingClientRect = this.valueCardPanel.nativeElement.getBoundingClientRect(); + const panelWidth = widgetBoundingClientRect.width - (pLeft + pRight); + const panelHeight = widgetBoundingClientRect.height - (pTop + pBottom); let scale: number; if (!this.horizontal) { const size = Math.min(panelWidth, panelHeight); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts index 7b46ccba4d..9b9ca8c19c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts @@ -19,8 +19,10 @@ import { BackgroundType, ColorSettings, constantColor, - cssUnit, DateFormatSettings, - Font, lastUpdateAgoDateFormat + cssUnit, + DateFormatSettings, + Font, + lastUpdateAgoDateFormat } from '@shared/models/widget-settings.models'; export enum ValueCardLayout { @@ -130,5 +132,5 @@ export const valueCardDefaultSettings = (horizontal: boolean): ValueCardWidgetSe blur: 3 } }, - padding: '12px' + padding: '24px' }); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html index 4a4ff409fd..95eb4a0ba1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.html @@ -15,12 +15,12 @@ limitations under the License. --> -
+
-
+
{{ icon }}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss index 9585cdb0eb..8dcefddd2a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.scss @@ -20,7 +20,7 @@ display: flex; align-items: center; justify-content: center; - padding: 16px; + padding: 0; > div:not(.tb-status-widget-overlay), > tb-icon { z-index: 1; } @@ -38,6 +38,7 @@ .tb-status-widget-content { width: 100%; height: 100%; + padding: 16px; position: relative; display: flex; flex-direction: column; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts index 77de5bc39c..d8d5b48ff6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.component.ts @@ -21,27 +21,29 @@ import { ElementRef, OnDestroy, OnInit, - Renderer2, ViewChild, + Renderer2, + ViewChild, ViewEncapsulation } from '@angular/core'; import { BasicActionWidgetComponent } from '@home/components/widget/lib/action/action-widget.models'; import { statusWidgetDefaultSettings, StatusWidgetLayout, - StatusWidgetSettings, StatusWidgetStateSettings + StatusWidgetSettings, + StatusWidgetStateSettings } from '@home/components/widget/lib/indicator/status-widget.models'; import { Observable } from 'rxjs'; import { backgroundStyle, ComponentStyle, iconStyle, - overlayStyle, resolveCssSize, + overlayStyle, + resolveCssSize, textStyle } from '@shared/models/widget-settings.models'; import { ResizeObserver } from '@juggle/resize-observer'; import { ImagePipe } from '@shared/pipe/image.pipe'; import { DomSanitizer } from '@angular/platform-browser'; -import { UtilsService } from '@core/services/utils.service'; import { ValueType } from '@shared/models/constants'; const initialStatusWidgetSize = 147; @@ -102,9 +104,7 @@ export class StatusWidgetComponent extends constructor(protected imagePipe: ImagePipe, protected sanitizer: DomSanitizer, private renderer: Renderer2, - private utils: UtilsService, - protected cd: ChangeDetectorRef, - private elementRef: ElementRef) { + protected cd: ChangeDetectorRef) { super(cd); } @@ -192,16 +192,13 @@ export class StatusWidgetComponent extends } private onResize() { - const paddingLeft = getComputedStyle(this.statusWidgetPanel.nativeElement).paddingLeft; - const paddingRight = getComputedStyle(this.statusWidgetPanel.nativeElement).paddingRight; - const paddingTop = getComputedStyle(this.statusWidgetPanel.nativeElement).paddingTop; - const paddingBottom = getComputedStyle(this.statusWidgetPanel.nativeElement).paddingBottom; - const pLeft = resolveCssSize(paddingLeft)[0]; - const pRight = resolveCssSize(paddingRight)[0]; - const pTop = resolveCssSize(paddingTop)[0]; - const pBottom = resolveCssSize(paddingBottom)[0]; - const panelWidth = this.statusWidgetPanel.nativeElement.getBoundingClientRect().width - (pLeft + pRight); - const panelHeight = this.statusWidgetPanel.nativeElement.getBoundingClientRect().height - (pTop + pBottom); + const computedStyle = getComputedStyle(this.statusWidgetPanel.nativeElement); + const [pLeft, pRight, pTop, pBottom] = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'] + .map(side => resolveCssSize(computedStyle[side])[0]); + + const widgetBoundingClientRect = this.statusWidgetPanel.nativeElement.getBoundingClientRect(); + const panelWidth = widgetBoundingClientRect.width - (pLeft + pRight); + const panelHeight = widgetBoundingClientRect.height - (pTop + pBottom); const targetSize = Math.min(panelWidth, panelHeight); const scale = targetSize / initialStatusWidgetSize; const width = initialStatusWidgetSize; @@ -229,7 +226,9 @@ export class StatusWidgetComponent extends this.showLabel = stateSettings.showLabel && this.layout !== StatusWidgetLayout.icon; this.showStatus = stateSettings.showStatus && this.layout !== StatusWidgetLayout.icon; this.icon = stateSettings.icon; - this.padding = stateSettings.backgroundDisabled.overlay.enabled || stateSettings.background.overlay.enabled ? undefined : this.settings.padding; + this.padding = stateSettings.backgroundDisabled.overlay.enabled || stateSettings.background.overlay.enabled + ? undefined + : this.settings.padding; const primaryColor = disabled ? stateSettings.primaryColorDisabled : stateSettings.primaryColor; const secondaryColor = disabled ? stateSettings.secondaryColorDisabled : stateSettings.secondaryColor; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts index 5bfede43f2..52d4ae5ff8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts @@ -35,7 +35,8 @@ import { backgroundStyle, ComponentStyle, iconStyle, - overlayStyle, resolveCssSize, + overlayStyle, + resolveCssSize, textStyle } from '@shared/models/widget-settings.models'; import { Observable } from 'rxjs'; @@ -46,8 +47,6 @@ import { ValueType } from '@shared/models/constants'; import { UtilsService } from '@core/services/utils.service'; const initialSwitchHeight = 60; -const horizontalLayoutPadding = 48; -const verticalLayoutPadding = 36; @Component({ selector: 'tb-single-switch-widget', @@ -233,19 +232,15 @@ export class SingleSwitchWidgetComponent extends } private onResize() { - const height = this.singleSwitchPanel.nativeElement.getBoundingClientRect().height; + const widgetBoundingClientRect = this.singleSwitchPanel.nativeElement.getBoundingClientRect(); + const height = widgetBoundingClientRect.height; const switchScale = height / initialSwitchHeight; const paddingScale = Math.min(switchScale, 1); - const paddingLeft = getComputedStyle(this.singleSwitchPanel.nativeElement).paddingLeft; - const paddingRight = getComputedStyle(this.singleSwitchPanel.nativeElement).paddingRight; - const paddingTop = getComputedStyle(this.singleSwitchPanel.nativeElement).paddingTop; - const paddingBottom = getComputedStyle(this.singleSwitchPanel.nativeElement).paddingBottom; - const pLeft = resolveCssSize(paddingLeft)[0]; - const pRight = resolveCssSize(paddingRight)[0]; - const pTop = resolveCssSize(paddingTop)[0]; - const pBottom = resolveCssSize(paddingBottom)[0]; - const panelWidth = this.singleSwitchPanel.nativeElement.getBoundingClientRect().width - (pLeft + pRight); - const panelHeight = this.singleSwitchPanel.nativeElement.getBoundingClientRect().height - (pTop + pBottom); + const computedStyle = getComputedStyle(this.singleSwitchPanel.nativeElement); + const [pLeft, pRight, pTop, pBottom] = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'] + .map(side => resolveCssSize(computedStyle[side])[0]); + const panelWidth = widgetBoundingClientRect.width - (pLeft + pRight); + const panelHeight = widgetBoundingClientRect.height - (pTop + pBottom); this.renderer.setStyle(this.singleSwitchContent.nativeElement, 'transform', `scale(1)`); this.renderer.setStyle(this.singleSwitchContent.nativeElement, 'width', 'auto'); let contentWidth = this.singleSwitchToggleRow.nativeElement.getBoundingClientRect().width; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts index 2fe9ab0d96..9f4ef7d369 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts @@ -219,5 +219,5 @@ export const singleSwitchDefaultSettings: SingleSwitchWidgetSettings = { blur: 3 } }, - padding: '12px' + padding: '18px 24px' }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts index 5c1a5518e8..9a1249970d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts @@ -14,7 +14,6 @@ /// limitations under the License. /// -import { BatteryLevelLayout } from '@home/components/widget/lib/indicator/battery-level-widget.models'; import { BackgroundSettings, BackgroundType, @@ -103,5 +102,5 @@ export const windSpeedDirectionDefaultSettings: WindSpeedDirectionWidgetSettings blur: 3 } }, - padding: '12px' + padding: '20px 24px 24px' }; From cf2fe93e23bf80a40aa179583ea1bde965d79b4f Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Tue, 10 Sep 2024 13:25:48 +0300 Subject: [PATCH 58/80] UI: Rename to sand filter --- .../scada_symbols/{stand-filter.svg => sand-filter.svg} | 7 ++++--- .../json/system/widget_bundles/scada_fluid_system.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) rename application/src/main/data/json/system/scada_symbols/{stand-filter.svg => sand-filter.svg} (99%) diff --git a/application/src/main/data/json/system/scada_symbols/stand-filter.svg b/application/src/main/data/json/system/scada_symbols/sand-filter.svg similarity index 99% rename from application/src/main/data/json/system/scada_symbols/stand-filter.svg rename to application/src/main/data/json/system/scada_symbols/sand-filter.svg index ebd1e28edd..1f9c0293d9 100644 --- a/application/src/main/data/json/system/scada_symbols/stand-filter.svg +++ b/application/src/main/data/json/system/scada_symbols/sand-filter.svg @@ -1,9 +1,10 @@ { - "title": "Stand filter", - "description": "Stand filter with configurable filtration mode option and various states.", + "title": "Sand filter", + "description": "Sand filter with configurable filtration mode option and various states.", "searchTags": [ - "filter" + "filter", + "sand" ], "widgetSizeX": 3, "widgetSizeY": 5, diff --git a/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json b/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json index 7ec1a0d60f..bcb92dce1d 100644 --- a/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json +++ b/application/src/main/data/json/system/widget_bundles/scada_fluid_system.json @@ -48,7 +48,7 @@ "long_bottom_filter", "short_top_filter", "long_top_filter", - "stand_filter", + "sand_filter", "horizontal_wheel_valve", "vertical_wheel_valve", "horizontal_ball_valve", From 53a975681c6b5ac0a348665dffcae612879aa1a5 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov <viacheslavklimov11@gmail.com> Date: Tue, 10 Sep 2024 13:42:27 +0300 Subject: [PATCH 59/80] Refactor versioned caching --- .../thingsboard/server/cache/CacheKey.java | 26 +++++++++++++++++++ .../cache/CaffeineTbTransactionalCache.java | 5 ---- .../server/cache/RedisTbCacheTransaction.java | 2 +- .../cache/RedisTbTransactionalCache.java | 16 ++++-------- .../server/cache/TbTransactionalCache.java | 8 +++--- .../cache/VersionedCaffeineTbCache.java | 2 +- .../server/cache/VersionedRedisTbCache.java | 19 +++++++++----- .../server/cache/VersionedTbCache.java | 2 +- .../server/cache/device/DeviceCacheKey.java | 9 +++++-- .../dao/asset/AssetProfileCacheKey.java | 9 +++++-- .../dao/attributes/AttributeCacheKey.java | 9 +++++-- .../dao/device/DeviceProfileCacheKey.java | 9 +++++-- .../entity/CachedVersionedEntityService.java | 3 ++- .../dao/entityview/EntityViewCacheKey.java | 9 +++++-- .../dao/timeseries/TsLatestCacheKey.java | 9 +++++-- 15 files changed, 93 insertions(+), 44 deletions(-) create mode 100644 common/cache/src/main/java/org/thingsboard/server/cache/CacheKey.java diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/CacheKey.java b/common/cache/src/main/java/org/thingsboard/server/cache/CacheKey.java new file mode 100644 index 0000000000..db7af5a32b --- /dev/null +++ b/common/cache/src/main/java/org/thingsboard/server/cache/CacheKey.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2024 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.cache; + +import java.io.Serializable; + +public interface CacheKey extends Serializable { + + default boolean isVersioned() { + return false; + } + +} diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/CaffeineTbTransactionalCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/CaffeineTbTransactionalCache.java index 4ce6571f1c..d2ea960e68 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/CaffeineTbTransactionalCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/CaffeineTbTransactionalCache.java @@ -54,11 +54,6 @@ public abstract class CaffeineTbTransactionalCache<K extends Serializable, V ext return SimpleTbCacheValueWrapper.wrap(cache.get(key)); } - @Override - public TbCacheValueWrapper<V> get(K key, boolean transactionMode) { - return get(key); - } - @Override public void put(K key, V value) { lock.lock(); diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbCacheTransaction.java b/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbCacheTransaction.java index 3dcb6e878f..fb852493ce 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbCacheTransaction.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbCacheTransaction.java @@ -31,7 +31,7 @@ public class RedisTbCacheTransaction<K extends Serializable, V extends Serializa @Override public void put(K key, V value) { - cache.put(key, value, connection, true); + cache.put(key, value, connection); } @Override diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java index fbf88bb5e4..8ee58ab8eb 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/RedisTbTransactionalCache.java @@ -87,17 +87,11 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend @Override public TbCacheValueWrapper<V> get(K key) { - return get(key, false); - } - - @Override - public TbCacheValueWrapper<V> get(K key, boolean transactionMode) { if (!cacheEnabled) { return null; } try (var connection = connectionFactory.getConnection()) { - byte[] rawKey = getRawKey(key); - byte[] rawValue = doGet(connection, rawKey, transactionMode); + byte[] rawValue = doGet(key, connection); if (rawValue == null || rawValue.length == 0) { return null; } else if (Arrays.equals(rawValue, BINARY_NULL_VALUE)) { @@ -114,8 +108,8 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend } } - protected byte[] doGet(RedisConnection connection, byte[] rawKey, boolean transactionMode) { - return connection.stringCommands().get(rawKey); + protected byte[] doGet(K key, RedisConnection connection) { + return connection.stringCommands().get(getRawKey(key)); } @Override @@ -124,11 +118,11 @@ public abstract class RedisTbTransactionalCache<K extends Serializable, V extend return; } try (var connection = connectionFactory.getConnection()) { - put(key, value, connection, false); + put(key, value, connection); } } - public void put(K key, V value, RedisConnection connection, boolean transactionMode) { + public void put(K key, V value, RedisConnection connection) { put(connection, key, value, RedisStringCommands.SetOption.UPSERT); } diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/TbTransactionalCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/TbTransactionalCache.java index 765c82a8db..44d5e09330 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/TbTransactionalCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/TbTransactionalCache.java @@ -27,8 +27,6 @@ public interface TbTransactionalCache<K extends Serializable, V extends Serializ TbCacheValueWrapper<V> get(K key); - TbCacheValueWrapper<V> get(K key, boolean transactionMode); - void put(K key, V value); void putIfAbsent(K key, V value); @@ -53,7 +51,7 @@ public interface TbTransactionalCache<K extends Serializable, V extends Serializ if (putToCache) { return getAndPutInTransaction(key, dbCall, cacheNullValue); } else { - TbCacheValueWrapper<V> cacheValueWrapper = get(key, true); + TbCacheValueWrapper<V> cacheValueWrapper = get(key); if (cacheValueWrapper != null) { return cacheValueWrapper.get(); } @@ -66,7 +64,7 @@ public interface TbTransactionalCache<K extends Serializable, V extends Serializ } default <R> R getAndPutInTransaction(K key, Supplier<R> dbCall, Function<V, R> cacheValueToResult, Function<R, V> dbValueToCacheValue, boolean cacheNullValue) { - TbCacheValueWrapper<V> cacheValueWrapper = get(key, true); + TbCacheValueWrapper<V> cacheValueWrapper = get(key); if (cacheValueWrapper != null) { V cacheValue = cacheValueWrapper.get(); return cacheValue != null ? cacheValueToResult.apply(cacheValue) : null; @@ -92,7 +90,7 @@ public interface TbTransactionalCache<K extends Serializable, V extends Serializ if (putToCache) { return getAndPutInTransaction(key, dbCall, cacheValueToResult, dbValueToCacheValue, cacheNullValue); } else { - TbCacheValueWrapper<V> cacheValueWrapper = get(key, true); + TbCacheValueWrapper<V> cacheValueWrapper = get(key); if (cacheValueWrapper != null) { var cacheValue = cacheValueWrapper.get(); return cacheValue == null ? null : cacheValueToResult.apply(cacheValue); diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java index f9c22ecc32..a8363e4f9a 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.util.TbPair; import java.io.Serializable; -public abstract class VersionedCaffeineTbCache<K extends Serializable, V extends Serializable & HasVersion> extends CaffeineTbTransactionalCache<K, V> implements VersionedTbCache<K, V> { +public abstract class VersionedCaffeineTbCache<K extends CacheKey, V extends Serializable & HasVersion> extends CaffeineTbTransactionalCache<K, V> implements VersionedTbCache<K, V> { public VersionedCaffeineTbCache(CacheManager cacheManager, String cacheName) { super(cacheManager, cacheName); diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java index 6ef3918a68..d101159ae3 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java @@ -30,7 +30,7 @@ import java.io.Serializable; import java.util.Arrays; @Slf4j -public abstract class VersionedRedisTbCache<K extends Serializable, V extends Serializable & HasVersion> extends RedisTbTransactionalCache<K, V> implements VersionedTbCache<K, V> { +public abstract class VersionedRedisTbCache<K extends CacheKey, V extends Serializable & HasVersion> extends RedisTbTransactionalCache<K, V> implements VersionedTbCache<K, V> { private static final int VERSION_SIZE = 8; private static final int VALUE_END_OFFSET = -1; @@ -79,15 +79,20 @@ public abstract class VersionedRedisTbCache<K extends Serializable, V extends Se } @Override - protected byte[] doGet(RedisConnection connection, byte[] rawKey, boolean transactionMode) { - if (transactionMode) { - return super.doGet(connection, rawKey, true); + protected byte[] doGet(K key, RedisConnection connection) { + if (!key.isVersioned()) { + return super.doGet(key, connection); } + byte[] rawKey = getRawKey(key); return connection.stringCommands().getRange(rawKey, VERSION_SIZE, VALUE_END_OFFSET); } @Override public void put(K key, V value) { + if (!key.isVersioned()) { + super.put(key, value); + return; + } Long version = getVersion(value); if (version == null) { return; @@ -96,9 +101,9 @@ public abstract class VersionedRedisTbCache<K extends Serializable, V extends Se } @Override - public void put(K key, V value, RedisConnection connection, boolean transactionMode) { - if (transactionMode) { - super.put(key, value, connection, true); // because scripting commands are not supported in transaction mode + public void put(K key, V value, RedisConnection connection) { + if (!key.isVersioned()) { + super.put(key, value, connection); // because scripting commands are not supported in transaction mode return; } Long version = getVersion(value); diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedTbCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedTbCache.java index faf63495b2..083ce93bac 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedTbCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedTbCache.java @@ -22,7 +22,7 @@ import java.util.Collection; import java.util.Optional; import java.util.function.Supplier; -public interface VersionedTbCache<K extends Serializable, V extends Serializable & HasVersion> extends TbTransactionalCache<K, V> { +public interface VersionedTbCache<K extends CacheKey, V extends Serializable & HasVersion> extends TbTransactionalCache<K, V> { TbCacheValueWrapper<V> get(K key); diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java b/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java index ed6258842d..c06b3eef27 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java @@ -19,17 +19,17 @@ import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; +import org.thingsboard.server.cache.CacheKey; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; import java.io.Serial; -import java.io.Serializable; @Getter @EqualsAndHashCode @RequiredArgsConstructor @Builder -public class DeviceCacheKey implements Serializable { +public class DeviceCacheKey implements CacheKey { @Serial private static final long serialVersionUID = 6366389552842340207L; @@ -61,4 +61,9 @@ public class DeviceCacheKey implements Serializable { } } + @Override + public boolean isVersioned() { + return deviceId != null; + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java index 1e91d43a8f..85bc12dea4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java @@ -16,14 +16,14 @@ package org.thingsboard.server.dao.asset; import lombok.Data; +import org.thingsboard.server.cache.CacheKey; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.TenantId; import java.io.Serial; -import java.io.Serializable; @Data -public class AssetProfileCacheKey implements Serializable { +public class AssetProfileCacheKey implements CacheKey { @Serial private static final long serialVersionUID = 8220455917177676472L; @@ -63,4 +63,9 @@ public class AssetProfileCacheKey implements Serializable { } } + @Override + public boolean isVersioned() { + return assetProfileId != null; + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java index 2cbd444f80..8204494828 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java @@ -18,16 +18,16 @@ package org.thingsboard.server.dao.attributes; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; +import org.thingsboard.server.cache.CacheKey; import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.id.EntityId; import java.io.Serial; -import java.io.Serializable; @EqualsAndHashCode @Getter @AllArgsConstructor -public class AttributeCacheKey implements Serializable { +public class AttributeCacheKey implements CacheKey { @Serial private static final long serialVersionUID = 2013369077925351881L; @@ -41,4 +41,9 @@ public class AttributeCacheKey implements Serializable { return "{" + entityId + "}" + scope + "_" + key; } + @Override + public boolean isVersioned() { + return true; + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java index ad886b6a7c..78056508dc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java @@ -16,15 +16,15 @@ package org.thingsboard.server.dao.device; import lombok.Data; +import org.thingsboard.server.cache.CacheKey; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.TenantId; import java.io.Serial; -import java.io.Serializable; @Data -public class DeviceProfileCacheKey implements Serializable { +public class DeviceProfileCacheKey implements CacheKey { @Serial private static final long serialVersionUID = 8220455917177676472L; @@ -74,4 +74,9 @@ public class DeviceProfileCacheKey implements Serializable { return tenantId + "_" + name; } + @Override + public boolean isVersioned() { + return deviceProfileId != null; + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/CachedVersionedEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/CachedVersionedEntityService.java index 356fafbbff..d8f322f2c7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/CachedVersionedEntityService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/CachedVersionedEntityService.java @@ -16,12 +16,13 @@ package org.thingsboard.server.dao.entity; import org.springframework.beans.factory.annotation.Autowired; +import org.thingsboard.server.cache.CacheKey; import org.thingsboard.server.cache.VersionedTbCache; import org.thingsboard.server.common.data.HasVersion; import java.io.Serializable; -public abstract class CachedVersionedEntityService<K extends Serializable, V extends Serializable & HasVersion, E> extends AbstractCachedEntityService<K, V, E> { +public abstract class CachedVersionedEntityService<K extends CacheKey, V extends Serializable & HasVersion, E> extends AbstractCachedEntityService<K, V, E> { @Autowired protected VersionedTbCache<K, V> cache; diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java index 59df403165..ff391b0f52 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java @@ -18,17 +18,17 @@ package org.thingsboard.server.dao.entityview; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; +import org.thingsboard.server.cache.CacheKey; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.TenantId; import java.io.Serial; -import java.io.Serializable; @Getter @EqualsAndHashCode @Builder -public class EntityViewCacheKey implements Serializable { +public class EntityViewCacheKey implements CacheKey { @Serial private static final long serialVersionUID = 5986277528222738163L; @@ -68,4 +68,9 @@ public class EntityViewCacheKey implements Serializable { } } + @Override + public boolean isVersioned() { + return entityViewId != null; + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java index 9880f21cc1..79756044fa 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java @@ -18,15 +18,15 @@ package org.thingsboard.server.dao.timeseries; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; +import org.thingsboard.server.cache.CacheKey; import org.thingsboard.server.common.data.id.EntityId; import java.io.Serial; -import java.io.Serializable; @EqualsAndHashCode @Getter @AllArgsConstructor -public class TsLatestCacheKey implements Serializable { +public class TsLatestCacheKey implements CacheKey { @Serial private static final long serialVersionUID = 2024369077925351881L; @@ -39,4 +39,9 @@ public class TsLatestCacheKey implements Serializable { return "{" + entityId + "}" + key; } + @Override + public boolean isVersioned() { + return true; + } + } From 7ad4a7b3ff03bb30133c1286907663ea6bf7841d Mon Sep 17 00:00:00 2001 From: YevhenBondarenko <ybondarenko@thingsboard.io> Date: Tue, 10 Sep 2024 13:15:28 +0200 Subject: [PATCH 60/80] removed wrong CONNECTION close header --- .../main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java | 1 - 1 file changed, 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java index b6a7234cac..58b63da978 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbHttpClient.java @@ -132,7 +132,6 @@ public class TbHttpClient { this.webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) - .defaultHeader(HttpHeaders.CONNECTION, "close") //In previous realization this header was present! (Added for hotfix "Connection reset") .build(); } catch (SSLException e) { throw new TbNodeException(e); From cf0d3183e7ec76f6d7e156bf37dc69d6e75ed7fb Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov <viacheslavklimov11@gmail.com> Date: Tue, 10 Sep 2024 15:23:29 +0300 Subject: [PATCH 61/80] Rename CacheKey to VersionedCacheKey --- .../server/cache/{CacheKey.java => VersionedCacheKey.java} | 2 +- .../thingsboard/server/cache/VersionedCaffeineTbCache.java | 2 +- .../org/thingsboard/server/cache/VersionedRedisTbCache.java | 2 +- .../java/org/thingsboard/server/cache/VersionedTbCache.java | 2 +- .../org/thingsboard/server/cache/device/DeviceCacheKey.java | 4 ++-- .../thingsboard/server/dao/asset/AssetProfileCacheKey.java | 4 ++-- .../thingsboard/server/dao/attributes/AttributeCacheKey.java | 4 ++-- .../thingsboard/server/dao/device/DeviceProfileCacheKey.java | 4 ++-- .../server/dao/entity/CachedVersionedEntityService.java | 4 ++-- .../thingsboard/server/dao/entityview/EntityViewCacheKey.java | 4 ++-- .../thingsboard/server/dao/timeseries/TsLatestCacheKey.java | 4 ++-- 11 files changed, 18 insertions(+), 18 deletions(-) rename common/cache/src/main/java/org/thingsboard/server/cache/{CacheKey.java => VersionedCacheKey.java} (92%) diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/CacheKey.java b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCacheKey.java similarity index 92% rename from common/cache/src/main/java/org/thingsboard/server/cache/CacheKey.java rename to common/cache/src/main/java/org/thingsboard/server/cache/VersionedCacheKey.java index db7af5a32b..f339d9def3 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/CacheKey.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCacheKey.java @@ -17,7 +17,7 @@ package org.thingsboard.server.cache; import java.io.Serializable; -public interface CacheKey extends Serializable { +public interface VersionedCacheKey extends Serializable { default boolean isVersioned() { return false; diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java index a8363e4f9a..535fa64cd9 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedCaffeineTbCache.java @@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.util.TbPair; import java.io.Serializable; -public abstract class VersionedCaffeineTbCache<K extends CacheKey, V extends Serializable & HasVersion> extends CaffeineTbTransactionalCache<K, V> implements VersionedTbCache<K, V> { +public abstract class VersionedCaffeineTbCache<K extends VersionedCacheKey, V extends Serializable & HasVersion> extends CaffeineTbTransactionalCache<K, V> implements VersionedTbCache<K, V> { public VersionedCaffeineTbCache(CacheManager cacheManager, String cacheName) { super(cacheManager, cacheName); diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java index d101159ae3..e9b64822e9 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedRedisTbCache.java @@ -30,7 +30,7 @@ import java.io.Serializable; import java.util.Arrays; @Slf4j -public abstract class VersionedRedisTbCache<K extends CacheKey, V extends Serializable & HasVersion> extends RedisTbTransactionalCache<K, V> implements VersionedTbCache<K, V> { +public abstract class VersionedRedisTbCache<K extends VersionedCacheKey, V extends Serializable & HasVersion> extends RedisTbTransactionalCache<K, V> implements VersionedTbCache<K, V> { private static final int VERSION_SIZE = 8; private static final int VALUE_END_OFFSET = -1; diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedTbCache.java b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedTbCache.java index 083ce93bac..c610825faf 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/VersionedTbCache.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/VersionedTbCache.java @@ -22,7 +22,7 @@ import java.util.Collection; import java.util.Optional; import java.util.function.Supplier; -public interface VersionedTbCache<K extends CacheKey, V extends Serializable & HasVersion> extends TbTransactionalCache<K, V> { +public interface VersionedTbCache<K extends VersionedCacheKey, V extends Serializable & HasVersion> extends TbTransactionalCache<K, V> { TbCacheValueWrapper<V> get(K key); diff --git a/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java b/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java index c06b3eef27..2a0819851e 100644 --- a/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java +++ b/common/cache/src/main/java/org/thingsboard/server/cache/device/DeviceCacheKey.java @@ -19,7 +19,7 @@ import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.thingsboard.server.cache.CacheKey; +import org.thingsboard.server.cache.VersionedCacheKey; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; @@ -29,7 +29,7 @@ import java.io.Serial; @EqualsAndHashCode @RequiredArgsConstructor @Builder -public class DeviceCacheKey implements CacheKey { +public class DeviceCacheKey implements VersionedCacheKey { @Serial private static final long serialVersionUID = 6366389552842340207L; diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java index 85bc12dea4..aa3f6ce89f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileCacheKey.java @@ -16,14 +16,14 @@ package org.thingsboard.server.dao.asset; import lombok.Data; -import org.thingsboard.server.cache.CacheKey; +import org.thingsboard.server.cache.VersionedCacheKey; import org.thingsboard.server.common.data.id.AssetProfileId; import org.thingsboard.server.common.data.id.TenantId; import java.io.Serial; @Data -public class AssetProfileCacheKey implements CacheKey { +public class AssetProfileCacheKey implements VersionedCacheKey { @Serial private static final long serialVersionUID = 8220455917177676472L; diff --git a/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java index 8204494828..def2c6c45c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/attributes/AttributeCacheKey.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.attributes; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; -import org.thingsboard.server.cache.CacheKey; +import org.thingsboard.server.cache.VersionedCacheKey; import org.thingsboard.server.common.data.AttributeScope; import org.thingsboard.server.common.data.id.EntityId; @@ -27,7 +27,7 @@ import java.io.Serial; @EqualsAndHashCode @Getter @AllArgsConstructor -public class AttributeCacheKey implements CacheKey { +public class AttributeCacheKey implements VersionedCacheKey { @Serial private static final long serialVersionUID = 2013369077925351881L; diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java index 78056508dc..55e8aa66eb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileCacheKey.java @@ -16,7 +16,7 @@ package org.thingsboard.server.dao.device; import lombok.Data; -import org.thingsboard.server.cache.CacheKey; +import org.thingsboard.server.cache.VersionedCacheKey; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.TenantId; @@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.id.TenantId; import java.io.Serial; @Data -public class DeviceProfileCacheKey implements CacheKey { +public class DeviceProfileCacheKey implements VersionedCacheKey { @Serial private static final long serialVersionUID = 8220455917177676472L; diff --git a/dao/src/main/java/org/thingsboard/server/dao/entity/CachedVersionedEntityService.java b/dao/src/main/java/org/thingsboard/server/dao/entity/CachedVersionedEntityService.java index d8f322f2c7..46045ab928 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entity/CachedVersionedEntityService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entity/CachedVersionedEntityService.java @@ -16,13 +16,13 @@ package org.thingsboard.server.dao.entity; import org.springframework.beans.factory.annotation.Autowired; -import org.thingsboard.server.cache.CacheKey; +import org.thingsboard.server.cache.VersionedCacheKey; import org.thingsboard.server.cache.VersionedTbCache; import org.thingsboard.server.common.data.HasVersion; import java.io.Serializable; -public abstract class CachedVersionedEntityService<K extends CacheKey, V extends Serializable & HasVersion, E> extends AbstractCachedEntityService<K, V, E> { +public abstract class CachedVersionedEntityService<K extends VersionedCacheKey, V extends Serializable & HasVersion, E> extends AbstractCachedEntityService<K, V, E> { @Autowired protected VersionedTbCache<K, V> cache; diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java index ff391b0f52..deb1d85b78 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewCacheKey.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.entityview; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; -import org.thingsboard.server.cache.CacheKey; +import org.thingsboard.server.cache.VersionedCacheKey; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityViewId; import org.thingsboard.server.common.data.id.TenantId; @@ -28,7 +28,7 @@ import java.io.Serial; @Getter @EqualsAndHashCode @Builder -public class EntityViewCacheKey implements CacheKey { +public class EntityViewCacheKey implements VersionedCacheKey { @Serial private static final long serialVersionUID = 5986277528222738163L; diff --git a/dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java b/dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java index 79756044fa..593bc55e1e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java +++ b/dao/src/main/java/org/thingsboard/server/dao/timeseries/TsLatestCacheKey.java @@ -18,7 +18,7 @@ package org.thingsboard.server.dao.timeseries; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; -import org.thingsboard.server.cache.CacheKey; +import org.thingsboard.server.cache.VersionedCacheKey; import org.thingsboard.server.common.data.id.EntityId; import java.io.Serial; @@ -26,7 +26,7 @@ import java.io.Serial; @EqualsAndHashCode @Getter @AllArgsConstructor -public class TsLatestCacheKey implements CacheKey { +public class TsLatestCacheKey implements VersionedCacheKey { @Serial private static final long serialVersionUID = 2024369077925351881L; From 1a9b555bf149eb3749eb7922464ed38772a0532c Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko <vprykhodko@thingsboard.io> Date: Tue, 10 Sep 2024 15:36:32 +0300 Subject: [PATCH 62/80] UI: Cards widget set default padding value is empty --- .../components/widget/lib/cards/value-card-widget.models.ts | 2 +- .../components/widget/lib/indicator/status-widget.models.ts | 2 +- .../widget/lib/rpc/single-switch-widget.component.ts | 6 ++++-- .../widget/lib/rpc/single-switch-widget.models.ts | 2 +- .../lib/weather/wind-speed-direction-widget.component.ts | 4 +--- .../lib/weather/wind-speed-direction-widget.models.ts | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts index 9b9ca8c19c..2ca299cb6e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/cards/value-card-widget.models.ts @@ -132,5 +132,5 @@ export const valueCardDefaultSettings = (horizontal: boolean): ValueCardWidgetSe blur: 3 } }, - padding: '24px' + padding: '' }); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts index d9daebba31..4dbea591f9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/indicator/status-widget.models.ts @@ -202,5 +202,5 @@ export const statusWidgetDefaultSettings: StatusWidgetSettings = { } } }, - padding: '16px' + padding: '' }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts index 52d4ae5ff8..63ed57628b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.component.ts @@ -47,6 +47,8 @@ import { ValueType } from '@shared/models/constants'; import { UtilsService } from '@core/services/utils.service'; const initialSwitchHeight = 60; +const horizontalLayoutPadding = 48; +const verticalLayoutPadding = 36; @Component({ selector: 'tb-single-switch-widget', @@ -239,8 +241,8 @@ export class SingleSwitchWidgetComponent extends const computedStyle = getComputedStyle(this.singleSwitchPanel.nativeElement); const [pLeft, pRight, pTop, pBottom] = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom'] .map(side => resolveCssSize(computedStyle[side])[0]); - const panelWidth = widgetBoundingClientRect.width - (pLeft + pRight); - const panelHeight = widgetBoundingClientRect.height - (pTop + pBottom); + const panelWidth = widgetBoundingClientRect.width - ((pLeft + pRight) || horizontalLayoutPadding * paddingScale); + const panelHeight = widgetBoundingClientRect.height - ((pTop + pBottom) || verticalLayoutPadding * paddingScale); this.renderer.setStyle(this.singleSwitchContent.nativeElement, 'transform', `scale(1)`); this.renderer.setStyle(this.singleSwitchContent.nativeElement, 'width', 'auto'); let contentWidth = this.singleSwitchToggleRow.nativeElement.getBoundingClientRect().width; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts index 9f4ef7d369..62aae25816 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/rpc/single-switch-widget.models.ts @@ -219,5 +219,5 @@ export const singleSwitchDefaultSettings: SingleSwitchWidgetSettings = { blur: 3 } }, - padding: '18px 24px' + padding: '' }; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts index 0381e8531f..929f41fe48 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.component.ts @@ -42,7 +42,6 @@ import { getSingleTsValueByDataKey, overlayStyle } from '@shared/models/widget-settings.models'; -import { WidgetComponent } from '@home/components/widget/widget.component'; import { formatValue, isDefinedAndNotNull, isNumeric } from '@core/utils'; import { ResizeObserver } from '@juggle/resize-observer'; import { Path, Svg, SVG, Text } from '@svgdotjs/svg.js'; @@ -112,8 +111,7 @@ export class WindSpeedDirectionWidgetComponent implements OnInit, OnDestroy, Aft private windDirection = 0; private centerValueText = 'N/A'; - constructor(private widgetComponent: WidgetComponent, - private imagePipe: ImagePipe, + constructor(private imagePipe: ImagePipe, private sanitizer: DomSanitizer, private renderer: Renderer2, private cd: ChangeDetectorRef) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts index 9a1249970d..5daa9e3d68 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/weather/wind-speed-direction-widget.models.ts @@ -102,5 +102,5 @@ export const windSpeedDirectionDefaultSettings: WindSpeedDirectionWidgetSettings blur: 3 } }, - padding: '20px 24px 24px' + padding: '' }; From 0d7a6bbaf39a7eea3e3adcdcd966bcae2c9077a9 Mon Sep 17 00:00:00 2001 From: Igor Kulikov <ikulikov@thingsboard.io> Date: Tue, 10 Sep 2024 18:01:49 +0300 Subject: [PATCH 63/80] UI: Improve dynamic components compilation - compile component in place to correctly handle template compile errors. --- .../dynamic-component-factory.service.ts | 45 ++++++++----------- .../shared/components/markdown.component.ts | 2 +- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts b/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts index 8414e6ff0e..d18797a1be 100644 --- a/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts +++ b/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts @@ -22,7 +22,7 @@ import { NgModule, NgModuleRef, OnDestroy, - Type, + Type, ɵNG_COMP_DEF, ɵresetCompiledComponents } from '@angular/core'; import { from, Observable, of } from 'rxjs'; @@ -64,7 +64,6 @@ export class DynamicComponentFactoryService { template: string, modules?: Type<any>[], preserveWhitespaces?: boolean, - compileAttempt = 1, styles?: string[]): Observable<DynamicComponentData<T>> { return from(import('@angular/compiler')).pipe( mergeMap(() => { @@ -78,32 +77,26 @@ export class DynamicComponentFactoryService { declarations: [comp], imports: moduleImports })(class DynamicComponentInstanceModule extends DynamicComponentModule {}); + + const module = this.compiler.compileModuleSync(dynamicComponentInstanceModule); + let moduleRef: NgModuleRef<any>; try { - const module = this.compiler.compileModuleSync(dynamicComponentInstanceModule); - let moduleRef: NgModuleRef<any>; - try { - moduleRef = module.create(this.injector); - } catch (e) { - this.compiler.clearCacheFor(module.moduleType); - throw e; - } - this.dynamicComponentModulesMap.set(comp, { - moduleRef, - moduleType: module.moduleType - }); - return of( { - componentType: comp, - componentModuleRef: moduleRef - }); - } catch (error) { - if (compileAttempt === 1) { - ɵresetCompiledComponents(); - return this.createDynamicComponent(componentType, template, modules, preserveWhitespaces, ++compileAttempt, styles); - } else { - console.error(error); - throw error; - } + moduleRef = module.create(this.injector); + // eslint-disable-next-line + comp[ɵNG_COMP_DEF]; + } catch (e) { + this.compiler.clearCacheFor(module.moduleType); + ɵresetCompiledComponents(); + throw e; } + this.dynamicComponentModulesMap.set(comp, { + moduleRef, + moduleType: module.moduleType + }); + return of( { + componentType: comp, + componentModuleRef: moduleRef + }); }) ); } diff --git a/ui-ngx/src/app/shared/components/markdown.component.ts b/ui-ngx/src/app/shared/components/markdown.component.ts index fc7c2d0d8d..069bca2b2d 100644 --- a/ui-ngx/src/app/shared/components/markdown.component.ts +++ b/ui-ngx/src/app/shared/components/markdown.component.ts @@ -160,7 +160,7 @@ export class TbMarkdownComponent implements OnChanges { }, template, compileModules, - true, 1, styles + true, styles ).subscribe((componentData) => { this.tbMarkdownInstanceComponentType = componentData.componentType; const injector: Injector = Injector.create({providers: [], parent: this.markdownContainer.injector}); From b142c72247f7050427d6ab49789ea40e403b263d Mon Sep 17 00:00:00 2001 From: mpetrov <mpetrov@thingsboard.io> Date: Tue, 10 Sep 2024 18:05:59 +0300 Subject: [PATCH 64/80] [4114] Added Modbus version mapping and OPC initial mapping --- ...gateway-connector-basic-config.abstract.ts | 72 ++ ...ay-connector-version-processor.abstract.ts | 3 +- .../modbus-version-processor.abstract.ts | 67 ++ .../opc-version-processor.abstract.ts | 55 ++ .../modbus-basic-config.abstract.ts | 81 ++ .../modbus-basic-config.component.ts | 110 +-- .../modbus-legacy-basic-config.component.ts | 76 ++ .../mqtt-basic-config.abstract.ts | 58 +- .../mqtt-basic-config.component.ts | 26 +- .../mqtt-legacy-basic-config.component.ts | 28 +- .../workers-config-control.component.html | 0 .../workers-config-control.component.ts | 0 .../opc-server-config.component.html | 0 .../opc-server-config.component.scss | 0 .../opc-server-config.component.ts | 0 .../opc-ua-basic-config.component.html | 0 .../opc-ua-basic-config.component.scss | 0 .../opc-ua-basic-config.component.ts | 81 +- .../opc-ua-legacy-basic-config.component.ts | 87 +++ .../gateway/gateway-connectors.component.html | 28 +- .../lib/gateway/gateway-widget.models.ts | 68 +- .../gateway-connector-version-mapping.util.ts | 8 + .../utils/modbus-version-mapping.util.ts | 77 ++ .../gateway/utils/opc-version-mapping.util.ts | 113 +++ .../widget/widget-components.module.ts | 14 +- .../connector-default-configs/modbus.json | 698 ++++++++++++------ .../connector-default-configs/opcua.json | 180 +++-- 27 files changed, 1393 insertions(+), 537 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-basic-config.abstract.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.abstract.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-legacy-basic-config.component.ts rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => mqtt}/workers-config-control/workers-config-control.component.html (100%) rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => mqtt}/workers-config-control/workers-config-control.component.ts (100%) rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => opc}/opc-server-config/opc-server-config.component.html (100%) rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => opc}/opc-server-config/opc-server-config.component.scss (100%) rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => opc}/opc-server-config/opc-server-config.component.ts (100%) rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => opc}/opc-ua-basic-config/opc-ua-basic-config.component.html (100%) rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => opc}/opc-ua-basic-config/opc-ua-basic-config.component.scss (100%) rename ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/{ => opc}/opc-ua-basic-config/opc-ua-basic-config.component.ts (51%) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-legacy-basic-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/modbus-version-mapping.util.ts create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-basic-config.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-basic-config.abstract.ts new file mode 100644 index 0000000000..d12e647254 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-basic-config.abstract.ts @@ -0,0 +1,72 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Directive, inject, Input, OnDestroy, TemplateRef } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, FormGroup, ValidationErrors, Validator } from '@angular/forms'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; + +@Directive() +export abstract class GatewayConnectorBasicConfigDirective<InputBasicConfig, OutputBasicConfig> + implements ControlValueAccessor, Validator, OnDestroy { + + @Input() generalTabContent: TemplateRef<any>; + + basicFormGroup: FormGroup; + + protected fb = inject(FormBuilder); + protected onChange!: (value: OutputBasicConfig) => void; + protected onTouched!: () => void; + protected destroy$ = new Subject<void>(); + + constructor() { + this.basicFormGroup = this.initBasicFormGroup(); + + this.basicFormGroup.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe((value) => this.onBasicFormGroupChange(value)); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + validate(): ValidationErrors | null { + return this.basicFormGroup.valid ? null : { basicFormGroup: { valid: false } }; + } + + registerOnChange(fn: (value: OutputBasicConfig) => void): void { + this.onChange = fn; + } + + registerOnTouched(fn: () => void): void { + this.onTouched = fn; + } + + writeValue(config: OutputBasicConfig): void { + this.basicFormGroup.setValue(this.mapConfigToFormValue(config), { emitEvent: false }); + } + + protected onBasicFormGroupChange(value: InputBasicConfig): void { + this.onChange(this.getMappedValue(value)); + this.onTouched(); + } + + protected abstract mapConfigToFormValue(config: OutputBasicConfig): InputBasicConfig; + protected abstract getMappedValue(config: InputBasicConfig): OutputBasicConfig; + protected abstract initBasicFormGroup(): FormGroup; +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts index e1addf0b71..5f06659823 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts @@ -15,6 +15,7 @@ /// import { GatewayConnector, GatewayVersion } from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { isString } from '@core/utils'; export abstract class GatewayConnectorVersionProcessor<BasicConfig> { gatewayVersion: number; @@ -48,7 +49,7 @@ export abstract class GatewayConnectorVersionProcessor<BasicConfig> { } private parseVersion(version: string): number { - return Number(version?.replace(/\./g, '')); + return isString(version) ? Number(version.replace(/\./g, '')) : 0; } protected abstract getDowngradedVersion(): GatewayConnector<BasicConfig>; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts new file mode 100644 index 0000000000..d520a5b1e8 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts @@ -0,0 +1,67 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { + GatewayConnector, + ModbusBasicConfig, + ModbusBasicConfig_v3_5_2, + ModbusLegacyBasicConfig, + ModbusLegacySlave, + ModbusMasterConfig, + ModbusSlave, +} from '../gateway-widget.models'; +import { GatewayConnectorVersionProcessor } from './gateway-connector-version-processor.abstract'; +import { ModbusVersionMappingUtil } from '@home/components/widget/lib/gateway/utils/modbus-version-mapping.util'; + +export class ModbusVersionProcessor extends GatewayConnectorVersionProcessor<any> { + + constructor( + protected gatewayVersionStr: string, + protected connector: GatewayConnector<ModbusBasicConfig> + ) { + super(gatewayVersionStr, connector); + } + getUpgradedVersion(): GatewayConnector<ModbusBasicConfig_v3_5_2> { + const configurationJson = this.connector.configurationJson; + return { + ...this.connector, + configurationJson: { + master: configurationJson.master + ? ModbusVersionMappingUtil.mapMasterToUpgradedVersion(configurationJson.master) + : {} as ModbusMasterConfig, + slave: configurationJson.slave + ? ModbusVersionMappingUtil.mapSlaveToUpgradedVersion(configurationJson.slave as ModbusLegacySlave) + : {} as ModbusSlave, + }, + configVersion: this.gatewayVersionStr + } as GatewayConnector<ModbusBasicConfig_v3_5_2>; + } + + getDowngradedVersion(): GatewayConnector<ModbusLegacyBasicConfig> { + const configurationJson = this.connector.configurationJson; + return { + ...this.connector, + configurationJson: { + ...configurationJson, + slave: configurationJson.slave + ? ModbusVersionMappingUtil.mapSlaveToDowngradedVersion(configurationJson.slave as ModbusSlave) + : {} as ModbusLegacySlave, + master: configurationJson.master, + }, + configVersion: this.gatewayVersionStr + } as GatewayConnector<ModbusLegacyBasicConfig>; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts new file mode 100644 index 0000000000..11c9908058 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts @@ -0,0 +1,55 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { + GatewayConnector, LegacyServerConfig, + OPCBasicConfig, + OPCBasicConfig_v3_5_2, + OPCLegacyBasicConfig, +} from '../gateway-widget.models'; +import { GatewayConnectorVersionProcessor } from './gateway-connector-version-processor.abstract'; +import { OpcVersionMappingUtil } from '@home/components/widget/lib/gateway/utils/opc-version-mapping.util'; + +export class OpcVersionProcessor extends GatewayConnectorVersionProcessor<OPCBasicConfig> { + + constructor( + protected gatewayVersionStr: string, + protected connector: GatewayConnector<OPCBasicConfig> + ) { + super(gatewayVersionStr, connector); + } + getUpgradedVersion(): GatewayConnector<OPCBasicConfig_v3_5_2> { + const server = this.connector.configurationJson.server as LegacyServerConfig; + return { + ...this.connector, + configurationJson: { + server: server ? OpcVersionMappingUtil.mapServerToUpgradedVersion(server) : {}, + mapping: server.mapping ? OpcVersionMappingUtil.mapMappingToUpgradedVersion(server.mapping) : [], + }, + configVersion: this.gatewayVersionStr + } as GatewayConnector<OPCBasicConfig_v3_5_2>; + } + + getDowngradedVersion(): GatewayConnector<OPCLegacyBasicConfig> { + return { + ...this.connector, + configurationJson: { + server: OpcVersionMappingUtil.mapServerToDowngradedVersion(this.connector.configurationJson as OPCBasicConfig_v3_5_2) + }, + configVersion: this.gatewayVersionStr + } as GatewayConnector<OPCLegacyBasicConfig>; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.abstract.ts new file mode 100644 index 0000000000..9e7be382d2 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.abstract.ts @@ -0,0 +1,81 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { Directive } from '@angular/core'; +import { FormControl, FormGroup, ValidationErrors } from '@angular/forms'; +import { takeUntil } from 'rxjs/operators'; +import { isEqual } from '@core/utils'; +import { GatewayConnectorBasicConfigDirective } from '@home/components/widget/lib/gateway/abstract/gateway-connector-basic-config.abstract'; +import { + ModbusBasicConfig, + ModbusBasicConfig_v3_5_2, +} from '@home/components/widget/lib/gateway/gateway-widget.models'; + +@Directive() +export abstract class ModbusBasicConfigDirective<BasicConfig> + extends GatewayConnectorBasicConfigDirective<ModbusBasicConfig_v3_5_2, BasicConfig> { + + enableSlaveControl: FormControl<boolean> = new FormControl(false); + + constructor() { + super(); + + this.enableSlaveControl.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(enable => { + this.updateSlaveEnabling(enable); + this.basicFormGroup.get('slave').updateValueAndValidity({ emitEvent: !!this.onChange }); + }); + } + + override writeValue(basicConfig: BasicConfig & ModbusBasicConfig): void { + super.writeValue(basicConfig); + this.onEnableSlaveControl(basicConfig); + } + + override validate(): ValidationErrors | null { + const { master, slave } = this.basicFormGroup.value; + const isEmpty = !master?.slaves?.length && (isEqual(slave, {}) || !slave); + if (!this.basicFormGroup.valid || isEmpty) { + return { basicFormGroup: { valid: false } }; + } + return null; + } + + protected override initBasicFormGroup(): FormGroup { + return this.fb.group({ + master: [], + slave: [], + }); + } + + protected override onBasicFormGroupChange(value: ModbusBasicConfig_v3_5_2): void { + super.onBasicFormGroupChange(value); + this.basicFormGroup.get('slave').updateValueAndValidity({ emitEvent: !!this.onChange }); + } + + private updateSlaveEnabling(isEnabled: boolean): void { + if (isEnabled) { + this.basicFormGroup.get('slave').enable({ emitEvent: false }); + } else { + this.basicFormGroup.get('slave').disable({ emitEvent: false }); + } + } + + private onEnableSlaveControl(basicConfig: ModbusBasicConfig): void { + this.enableSlaveControl.setValue(!!basicConfig.slave && !isEqual(basicConfig.slave, {})); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index aa0424da93..21c37ed147 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -14,28 +14,21 @@ /// limitations under the License. /// -import { ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy, TemplateRef } from '@angular/core'; +import { ChangeDetectionStrategy, Component, forwardRef } from '@angular/core'; +import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms'; import { - ControlValueAccessor, - FormBuilder, - FormControl, - FormGroup, - NG_VALIDATORS, - NG_VALUE_ACCESSOR, - UntypedFormControl, - ValidationErrors, - Validator, -} from '@angular/forms'; -import { ModbusBasicConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { SharedModule } from '@shared/shared.module'; + ModbusBasicConfig_v3_5_2, + ModbusMasterConfig, + ModbusSlave +} from '@home/components/widget/lib/gateway/gateway-widget.models'; import { CommonModule } from '@angular/common'; -import { takeUntil } from 'rxjs/operators'; -import { Subject } from 'rxjs'; - -import { EllipsisChipListDirective } from '@shared/directives/ellipsis-chip-list.directive'; +import { SharedModule } from '@shared/shared.module'; import { ModbusSlaveConfigComponent } from '../modbus-slave-config/modbus-slave-config.component'; import { ModbusMasterTableComponent } from '../modbus-master-table/modbus-master-table.component'; -import { isEqual } from '@core/utils'; +import { EllipsisChipListDirective } from '@shared/directives/ellipsis-chip-list.directive'; +import { + ModbusBasicConfigDirective +} from '@home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.abstract'; @Component({ selector: 'tb-modbus-basic-config', @@ -63,80 +56,19 @@ import { isEqual } from '@core/utils'; ], styleUrls: ['./modbus-basic-config.component.scss'], }) +export class ModbusBasicConfigComponent extends ModbusBasicConfigDirective<ModbusBasicConfig_v3_5_2> { -export class ModbusBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy { - - @Input() generalTabContent: TemplateRef<any>; - - basicFormGroup: FormGroup; - enableSlaveControl: FormControl<boolean>; - - onChange: (value: ModbusBasicConfig) => void; - onTouched: () => void; - - private destroy$ = new Subject<void>(); - - constructor(private fb: FormBuilder) { - this.basicFormGroup = this.fb.group({ - master: [], - slave: [], - }); - this.enableSlaveControl = new FormControl(false); - - this.basicFormGroup.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(({ master, slave }) => { - this.onChange({ master, slave: slave ?? {} }); - this.onTouched(); - }); - - this.enableSlaveControl.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(enable => { - this.updateSlaveEnabling(enable); - this.basicFormGroup.get('slave').updateValueAndValidity({emitEvent: !!this.onChange}); - }); - } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } - - registerOnChange(fn: (value: ModbusBasicConfig) => void): void { - this.onChange = fn; - } - - registerOnTouched(fn: () => void): void { - this.onTouched = fn; - } - - writeValue(basicConfig: ModbusBasicConfig): void { - const editedBase = { - slave: basicConfig.slave ?? {}, - master: basicConfig.master ?? {}, + protected override mapConfigToFormValue(config: ModbusBasicConfig_v3_5_2): ModbusBasicConfig_v3_5_2 { + return { + master: config.master ?? {} as ModbusMasterConfig, + slave: config.slave ?? {} as ModbusSlave, }; - - this.basicFormGroup.setValue(editedBase, {emitEvent: false}); - this.enableSlaveControl.setValue(!!basicConfig.slave && !isEqual(basicConfig.slave, {})); - } - - validate(basicFormControl: UntypedFormControl): ValidationErrors | null { - const { master, slave } = basicFormControl.value; - const isEmpty = !master?.slaves?.length && (isEqual(slave, {}) || !slave); - if (!this.basicFormGroup.valid || isEmpty) { - return { - basicFormGroup: {valid: false} - }; - } - return null; } - private updateSlaveEnabling(isEnabled: boolean): void { - if (isEnabled) { - this.basicFormGroup.get('slave').enable({emitEvent: false}); - } else { - this.basicFormGroup.get('slave').disable({emitEvent: false}); - } + protected override getMappedValue(value: ModbusBasicConfig_v3_5_2): ModbusBasicConfig_v3_5_2 { + return { + master: value.master, + slave: value.slave, + }; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-legacy-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-legacy-basic-config.component.ts new file mode 100644 index 0000000000..50f7d833fa --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-legacy-basic-config.component.ts @@ -0,0 +1,76 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { ChangeDetectionStrategy, Component, forwardRef } from '@angular/core'; +import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { + ModbusBasicConfig_v3_5_2, + ModbusLegacyBasicConfig, ModbusLegacySlave, + ModbusMasterConfig, + ModbusSlave +} from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { ModbusSlaveConfigComponent } from '../modbus-slave-config/modbus-slave-config.component'; +import { ModbusMasterTableComponent } from '../modbus-master-table/modbus-master-table.component'; +import { EllipsisChipListDirective } from '@shared/directives/ellipsis-chip-list.directive'; +import { ModbusVersionMappingUtil } from '@home/components/widget/lib/gateway/utils/modbus-version-mapping.util'; +import { + ModbusBasicConfigDirective +} from '@home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.abstract'; + +@Component({ + selector: 'tb-modbus-legacy-basic-config', + templateUrl: './modbus-basic-config.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ModbusLegacyBasicConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ModbusLegacyBasicConfigComponent), + multi: true + } + ], + standalone: true, + imports: [ + CommonModule, + SharedModule, + ModbusSlaveConfigComponent, + ModbusMasterTableComponent, + EllipsisChipListDirective, + ], + styleUrls: ['./modbus-basic-config.component.scss'], +}) +export class ModbusLegacyBasicConfigComponent extends ModbusBasicConfigDirective<ModbusLegacyBasicConfig> { + + protected override mapConfigToFormValue(config: ModbusLegacyBasicConfig): ModbusBasicConfig_v3_5_2 { + return { + master: config.master ? ModbusVersionMappingUtil.mapMasterToUpgradedVersion(config.master) : {} as ModbusMasterConfig, + slave: config.slave ? ModbusVersionMappingUtil.mapSlaveToUpgradedVersion(config.slave) : {} as ModbusSlave, + }; + } + + protected override getMappedValue(value: ModbusBasicConfig_v3_5_2): ModbusLegacyBasicConfig { + return { + master: value.master, + slave: value.slave ? ModbusVersionMappingUtil.mapSlaveToDowngradedVersion(value.slave) : {} as ModbusLegacySlave, + }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts index aeef688333..ce87d80a75 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract.ts @@ -14,63 +14,33 @@ /// limitations under the License. /// -import { ControlValueAccessor, FormBuilder, FormGroup, ValidationErrors, Validator } from '@angular/forms'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; +import { Directive } from '@angular/core'; +import { FormGroup } from '@angular/forms'; import { MappingType, - MQTTBasicConfig, + MQTTBasicConfig, MQTTBasicConfig_v3_5_2, RequestMappingData, RequestMappingValue, RequestType } from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { Directive, OnDestroy } from '@angular/core'; import { isObject } from '@core/utils'; +import { + GatewayConnectorBasicConfigDirective +} from '@home/components/widget/lib/gateway/abstract/gateway-connector-basic-config.abstract'; @Directive() -export abstract class AbstractMqttBasicConfigComponent<BasicConfig> implements ControlValueAccessor, Validator, OnDestroy { +export abstract class MqttBasicConfigDirective<BasicConfig> + extends GatewayConnectorBasicConfigDirective<MQTTBasicConfig_v3_5_2, BasicConfig> { - basicFormGroup: FormGroup; MappingType = MappingType; - private destroy$ = new Subject<void>(); - - private onChange: (value: BasicConfig) => void; - private onTouched: () => void; - - constructor(protected fb: FormBuilder) { - this.basicFormGroup = this.fb.group({ + protected override initBasicFormGroup(): FormGroup { + return this.fb.group({ mapping: [], requestsMapping: [], broker: [], workers: [], }); - - this.basicFormGroup.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(value => { - this.onChange(this.getMappedMQTTConfig(value)); - this.onTouched(); - }); - } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } - - registerOnChange(fn: (value: BasicConfig) => void): void { - this.onChange = fn; - } - - registerOnTouched(fn: () => void): void { - this.onTouched = fn; - } - - validate(): ValidationErrors | null { - return this.basicFormGroup.valid ? null : { - basicFormGroup: {valid: false} - }; } protected getRequestDataArray(value: Record<RequestType, RequestMappingData[]>): RequestMappingData[] { @@ -103,6 +73,10 @@ export abstract class AbstractMqttBasicConfigComponent<BasicConfig> implements C }); } - abstract writeValue(basicConfig: BasicConfig): void; - protected abstract getMappedMQTTConfig(basicConfig: MQTTBasicConfig): BasicConfig; + writeValue(basicConfig: BasicConfig): void { + this.basicFormGroup.setValue(this.mapConfigToFormValue(basicConfig), { emitEvent: false }); + } + + protected abstract override mapConfigToFormValue(config: BasicConfig): MQTTBasicConfig_v3_5_2; + protected abstract override getMappedValue(config: MQTTBasicConfig): BasicConfig; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts index 541866dab8..9af627352a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component.ts @@ -14,16 +14,17 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, TemplateRef, ChangeDetectionStrategy } from '@angular/core'; +import { Component, forwardRef, ChangeDetectionStrategy } from '@angular/core'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms'; import { + BrokerConfig, MQTTBasicConfig_v3_5_2, RequestMappingData, RequestMappingValue, - RequestType + RequestType, WorkersConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { - AbstractMqttBasicConfigComponent + MqttBasicConfigDirective } from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract'; import { isDefinedAndNotNull } from '@core/utils'; import { CommonModule } from '@angular/common'; @@ -33,7 +34,7 @@ import { } from '@home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component'; import { WorkersConfigControlComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component'; +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/workers-config-control/workers-config-control.component'; import { BrokerConfigControlComponent } from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component'; @@ -68,27 +69,22 @@ import { MappingTableComponent, ], }) -export class MqttBasicConfigComponent extends AbstractMqttBasicConfigComponent<MQTTBasicConfig_v3_5_2> { +export class MqttBasicConfigComponent extends MqttBasicConfigDirective<MQTTBasicConfig_v3_5_2> { - @Input() - generalTabContent: TemplateRef<any>; - - writeValue(basicConfig: MQTTBasicConfig_v3_5_2): void { + protected override mapConfigToFormValue(basicConfig: MQTTBasicConfig_v3_5_2): MQTTBasicConfig_v3_5_2 { const { broker, mapping = [], requestsMapping } = basicConfig; - const editedBase = { + return{ workers: broker && (broker.maxNumberOfWorkers || broker.maxMessageNumberPerWorker) ? { maxNumberOfWorkers: broker.maxNumberOfWorkers, maxMessageNumberPerWorker: broker.maxMessageNumberPerWorker, - } : {}, + } : {} as WorkersConfig, mapping: mapping ?? [], - broker: broker ?? {}, + broker: broker ?? {} as BrokerConfig, requestsMapping: this.getRequestDataArray(requestsMapping as Record<RequestType, RequestMappingData[]>), }; - - this.basicFormGroup.setValue(editedBase, {emitEvent: false}); } - protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig_v3_5_2): MQTTBasicConfig_v3_5_2 { + protected override getMappedValue(basicConfig: MQTTBasicConfig_v3_5_2): MQTTBasicConfig_v3_5_2 { let { broker, workers, mapping, requestsMapping } = basicConfig || {}; if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts index 2ca5eba000..e4577c653e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-legacy-basic-config.component.ts @@ -14,18 +14,19 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, TemplateRef, ChangeDetectionStrategy } from '@angular/core'; +import { Component, forwardRef, ChangeDetectionStrategy } from '@angular/core'; import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms'; import { + BrokerConfig, MQTTBasicConfig_v3_5_2, MQTTLegacyBasicConfig, RequestMappingData, RequestMappingValue, - RequestType + RequestType, WorkersConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { MqttVersionMappingUtil } from '@home/components/widget/lib/gateway/utils/mqtt-version-mapping.util'; import { - AbstractMqttBasicConfigComponent + MqttBasicConfigDirective } from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.abstract'; import { isDefinedAndNotNull } from '@core/utils'; import { CommonModule } from '@angular/common'; @@ -35,7 +36,7 @@ import { } from '@home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component'; import { WorkersConfigControlComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component'; +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/workers-config-control/workers-config-control.component'; import { BrokerConfigControlComponent } from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component'; @@ -70,12 +71,9 @@ import { MappingTableComponent, ], }) -export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigComponent<MQTTLegacyBasicConfig> { +export class MqttLegacyBasicConfigComponent extends MqttBasicConfigDirective<MQTTLegacyBasicConfig> { - @Input() - generalTabContent: TemplateRef<any>; - - writeValue(basicConfig: MQTTLegacyBasicConfig): void { + protected override mapConfigToFormValue(config: MQTTLegacyBasicConfig): MQTTBasicConfig_v3_5_2 { const { broker, mapping = [], @@ -84,7 +82,7 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo attributeRequests = [], attributeUpdates = [], serverSideRpc = [] - } = basicConfig; + } = config as MQTTLegacyBasicConfig; const updatedRequestMapping = MqttVersionMappingUtil.mapRequestsToUpgradedVersion({ connectRequests, disconnectRequests, @@ -92,20 +90,18 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo attributeUpdates, serverSideRpc }); - const editedBase = { + return { workers: broker && (broker.maxNumberOfWorkers || broker.maxMessageNumberPerWorker) ? { maxNumberOfWorkers: broker.maxNumberOfWorkers, maxMessageNumberPerWorker: broker.maxMessageNumberPerWorker, - } : {}, + } : {} as WorkersConfig, mapping: MqttVersionMappingUtil.mapMappingToUpgradedVersion(mapping) || [], - broker: broker || {}, + broker: broker || {} as BrokerConfig, requestsMapping: this.getRequestDataArray(updatedRequestMapping), }; - - this.basicFormGroup.setValue(editedBase, {emitEvent: false}); } - protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig_v3_5_2): MQTTLegacyBasicConfig { + protected override getMappedValue(basicConfig: MQTTBasicConfig_v3_5_2): MQTTLegacyBasicConfig { let { broker, workers, mapping, requestsMapping } = basicConfig || {}; if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/workers-config-control/workers-config-control.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component.html rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/workers-config-control/workers-config-control.component.html diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/workers-config-control/workers-config-control.component.ts similarity index 100% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component.ts rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt/workers-config-control/workers-config-control.component.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.html rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.html diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.scss similarity index 100% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.scss rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.scss diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.ts similarity index 100% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.ts rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.html rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.html diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.scss similarity index 100% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.scss rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.scss diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.ts similarity index 51% rename from ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.ts rename to ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.ts index b6cf4a4081..1a45e74c7a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.ts @@ -14,34 +14,25 @@ /// limitations under the License. /// -import { ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy, TemplateRef } from '@angular/core'; +import { ChangeDetectionStrategy, Component, forwardRef } from '@angular/core'; +import { FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms'; import { - ControlValueAccessor, - FormBuilder, - FormGroup, - NG_VALIDATORS, - NG_VALUE_ACCESSOR, - ValidationErrors, - Validator, -} from '@angular/forms'; -import { - ConnectorType, MappingType, - OPCBasicConfig, + OPCBasicConfig_v3_5_2, + ServerConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { SharedModule } from '@shared/shared.module'; import { CommonModule } from '@angular/common'; -import { takeUntil } from 'rxjs/operators'; -import { Subject } from 'rxjs'; +import { SharedModule } from '@shared/shared.module'; +import { MappingTableComponent } from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; import { SecurityConfigComponent } from '@home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component'; -import { - MappingTableComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; import { OpcServerConfigComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component'; +} from '@home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component'; +import { + GatewayConnectorBasicConfigDirective +} from '@home/components/widget/lib/gateway/abstract/gateway-connector-basic-config.abstract'; @Component({ selector: 'tb-opc-ua-basic-config', @@ -69,58 +60,28 @@ import { ], styleUrls: ['./opc-ua-basic-config.component.scss'] }) - -export class OpcUaBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy { - @Input() generalTabContent: TemplateRef<any>; +export class OpcUaBasicConfigComponent extends GatewayConnectorBasicConfigDirective<OPCBasicConfig_v3_5_2, OPCBasicConfig_v3_5_2> { mappingTypes = MappingType; - basicFormGroup: FormGroup; - - onChange!: (value: string) => void; - onTouched!: () => void; - - protected readonly connectorType = ConnectorType; - private destroy$ = new Subject<void>(); - constructor(private fb: FormBuilder) { - this.basicFormGroup = this.fb.group({ + protected override initBasicFormGroup(): FormGroup { + return this.fb.group({ mapping: [], server: [], }); - - this.basicFormGroup.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(value => { - this.onChange(value); - this.onTouched(); - }); - } - - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } - - registerOnChange(fn: (value: string) => void): void { - this.onChange = fn; - } - - registerOnTouched(fn: () => void): void { - this.onTouched = fn; } - writeValue(basicConfig: OPCBasicConfig): void { - const editedBase = { - server: basicConfig.server || {}, - mapping: basicConfig.mapping || [], + protected override mapConfigToFormValue(config: OPCBasicConfig_v3_5_2): OPCBasicConfig_v3_5_2 { + return { + server: config.server ?? {} as ServerConfig, + mapping: config.mapping ?? [], }; - - this.basicFormGroup.setValue(editedBase, {emitEvent: false}); } - validate(): ValidationErrors | null { - return this.basicFormGroup.valid ? null : { - basicFormGroup: {valid: false} + protected override getMappedValue(value: OPCBasicConfig_v3_5_2): OPCBasicConfig_v3_5_2 { + return { + server: value.server, + mapping: value.mapping, }; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-legacy-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-legacy-basic-config.component.ts new file mode 100644 index 0000000000..12e05205a2 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-legacy-basic-config.component.ts @@ -0,0 +1,87 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { ChangeDetectionStrategy, Component, forwardRef } from '@angular/core'; +import { FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { + MappingType, + OPCBasicConfig_v3_5_2, + OPCLegacyBasicConfig, ServerConfig, +} from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { MappingTableComponent } from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; +import { + SecurityConfigComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component'; +import { + OpcServerConfigComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component'; +import { + GatewayConnectorBasicConfigDirective +} from '@home/components/widget/lib/gateway/abstract/gateway-connector-basic-config.abstract'; +import { OpcVersionMappingUtil } from '@home/components/widget/lib/gateway/utils/opc-version-mapping.util'; + +@Component({ + selector: 'tb-opc-ua-legacy-basic-config', + templateUrl: './opc-ua-basic-config.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => OpcUaLegacyBasicConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => OpcUaLegacyBasicConfigComponent), + multi: true + } + ], + standalone: true, + imports: [ + CommonModule, + SharedModule, + SecurityConfigComponent, + MappingTableComponent, + OpcServerConfigComponent, + ], + styleUrls: ['./opc-ua-basic-config.component.scss'] +}) +export class OpcUaLegacyBasicConfigComponent extends GatewayConnectorBasicConfigDirective<OPCBasicConfig_v3_5_2, OPCLegacyBasicConfig> { + + mappingTypes = MappingType; + + protected override initBasicFormGroup(): FormGroup { + return this.fb.group({ + mapping: [], + server: [], + }); + } + + protected override mapConfigToFormValue(config: OPCLegacyBasicConfig): OPCBasicConfig_v3_5_2 { + return { + server: config.server ? OpcVersionMappingUtil.mapServerToUpgradedVersion(config.server) : {} as ServerConfig, + mapping: config.server?.mapping ? OpcVersionMappingUtil.mapMappingToUpgradedVersion(config.server.mapping) : [], + }; + } + + protected override getMappedValue(value: OPCBasicConfig_v3_5_2): OPCLegacyBasicConfig { + return { + server: OpcVersionMappingUtil.mapServerToDowngradedVersion(value), + }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html index f0459496df..7c495d34f1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.html @@ -186,14 +186,26 @@ <tb-mqtt-legacy-basic-config formControlName="basicConfig" [generalTabContent]="generalTabContent"/> </ng-template> </ng-container> - <tb-opc-ua-basic-config *ngSwitchCase="ConnectorType.OPCUA" - formControlName="basicConfig" - [generalTabContent]="generalTabContent"> - </tb-opc-ua-basic-config> - <tb-modbus-basic-config *ngSwitchCase="ConnectorType.MODBUS" - formControlName="basicConfig" - [generalTabContent]="generalTabContent"> - </tb-modbus-basic-config> + <ng-container *ngSwitchCase="ConnectorType.OPCUA"> + <tb-opc-ua-basic-config + *ngIf="connectorForm.get('configVersion').value === GatewayVersion.Current else legacy" + formControlName="basicConfig" + [generalTabContent]="generalTabContent" + /> + <ng-template #legacy> + <tb-opc-ua-legacy-basic-config formControlName="basicConfig" [generalTabContent]="generalTabContent"/> + </ng-template> + </ng-container> + <ng-container *ngSwitchCase="ConnectorType.MODBUS"> + <tb-modbus-basic-config + *ngIf="connectorForm.get('configVersion').value === GatewayVersion.Current else legacy" + formControlName="basicConfig" + [generalTabContent]="generalTabContent" + /> + <ng-template #legacy> + <tb-modbus-legacy-basic-config formControlName="basicConfig" [generalTabContent]="generalTabContent"/> + </ng-template> + </ng-container> </ng-container> </ng-container> <ng-template #defaultConfig> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index f7acac12e6..8a0e4005fd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -199,9 +199,9 @@ export type ConnectorMappingFormValue = DeviceConnectorMapping | RequestMappingF export type ConnectorBaseConfig = ConnectorBaseConfig_v_3_5_2 | ConnectorLegacyConfig; -export type ConnectorLegacyConfig = ConnectorBaseInfo | MQTTLegacyBasicConfig | OPCBasicConfig | ModbusBasicConfig; +export type ConnectorLegacyConfig = ConnectorBaseInfo | MQTTLegacyBasicConfig | OPCLegacyBasicConfig | ModbusBasicConfig; -export type ConnectorBaseConfig_v_3_5_2 = ConnectorBaseInfo | MQTTBasicConfig_v3_5_2; +export type ConnectorBaseConfig_v_3_5_2 = ConnectorBaseInfo | MQTTBasicConfig_v3_5_2 | OPCBasicConfig_v3_5_2; export interface ConnectorBaseInfo { name: string; @@ -230,16 +230,34 @@ export interface MQTTLegacyBasicConfig { serverSideRpc: LegacyRequestMappingData[]; } -export interface OPCBasicConfig { +export type OPCBasicConfig = OPCBasicConfig_v3_5_2 | OPCLegacyBasicConfig; + +export interface OPCBasicConfig_v3_5_2 { mapping: DeviceConnectorMapping[]; server: ServerConfig; } -export interface ModbusBasicConfig { +export interface OPCLegacyBasicConfig { + server: LegacyServerConfig; +} + +export interface LegacyServerConfig extends Omit<ServerConfig, 'enableSubscriptions'> { + mapping: LegacyDeviceConnectorMapping[]; + disableSubscriptions: boolean; +} + +export type ModbusBasicConfig = ModbusBasicConfig_v3_5_2 | ModbusLegacyBasicConfig; + +export interface ModbusBasicConfig_v3_5_2 { master: ModbusMasterConfig; slave: ModbusSlave; } +export interface ModbusLegacyBasicConfig { + master: ModbusMasterConfig; + slave: ModbusLegacySlave; +} + export interface WorkersConfig { maxNumberOfWorkers: number; maxMessageNumberPerWorker: number; @@ -258,12 +276,22 @@ export interface Attribute { value: string; } +export interface LegacyAttribute { + key: string; + path: string; +} + export interface Timeseries { key: string; type: string; value: string; } +export interface LegacyTimeseries { + key: string; + path: string; +} + interface RpcArgument { type: string; value: number; @@ -274,12 +302,22 @@ export interface RpcMethod { arguments: RpcArgument[]; } +export interface LegacyRpcMethod { + method: string; + arguments: unknown[]; +} + export interface AttributesUpdate { key: string; type: string; value: string; } +export interface LegacyDeviceAttributeUpdate { + attributeOnThingsBoard: string; + attributeOnDevice: string; +} + export interface Converter { type: ConvertorType; deviceInfo?: ConnectorDeviceInfo; @@ -333,6 +371,15 @@ export interface DeviceConnectorMapping { attributes_updates?: AttributesUpdate[]; } +export interface LegacyDeviceConnectorMapping { + deviceNamePattern: string; + deviceTypePattern: string; + attributes?: LegacyAttribute[]; + timeseries?: LegacyTimeseries[]; + rpc_methods?: LegacyRpcMethod[]; + attributes_updates?: LegacyDeviceAttributeUpdate[]; +} + export enum ConnectorType { MQTT = 'mqtt', MODBUS = 'modbus', @@ -1069,7 +1116,7 @@ export interface SlaveConfig { pollPeriod: number; unitId: number; deviceName: string; - deviceType: string; + deviceType?: string; sendDataOnlyOnChange: boolean; connectAttemptTimeMs: number; connectAttemptCount: number; @@ -1121,8 +1168,19 @@ export interface ModbusSlave { security: ModbusSecurity; } +export interface ModbusLegacySlave extends Omit<ModbusSlave, 'values'> { + values: ModbusLegacyRegisterValues; +} + export type ModbusValuesState = ModbusRegisterValues | ModbusValues; +export interface ModbusLegacyRegisterValues { + holding_registers: ModbusValues[]; + coils_initializer: ModbusValues[]; + input_registers: ModbusValues[]; + discrete_inputs: ModbusValues[]; +} + export interface ModbusRegisterValues { holding_registers: ModbusValues; coils_initializer: ModbusValues; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts index 12f3a7c439..90c89ea316 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util.ts @@ -17,9 +17,13 @@ import { ConnectorType, GatewayConnector, + ModbusBasicConfig, MQTTBasicConfig, + OPCBasicConfig, } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { MqttVersionProcessor } from '@home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract'; +import { OpcVersionProcessor } from '@home/components/widget/lib/gateway/abstract/opc-version-processor.abstract'; +import { ModbusVersionProcessor } from '@home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract'; export abstract class GatewayConnectorVersionMappingUtil { @@ -27,6 +31,10 @@ export abstract class GatewayConnectorVersionMappingUtil { switch(connector.type) { case ConnectorType.MQTT: return new MqttVersionProcessor(gatewayVersion, connector as GatewayConnector<MQTTBasicConfig>).getProcessedByVersion(); + case ConnectorType.OPCUA: + return new OpcVersionProcessor(gatewayVersion, connector as GatewayConnector<OPCBasicConfig>).getProcessedByVersion(); + case ConnectorType.MODBUS: + return new ModbusVersionProcessor(gatewayVersion, connector as GatewayConnector<ModbusBasicConfig>).getProcessedByVersion(); default: return connector; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/modbus-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/modbus-version-mapping.util.ts new file mode 100644 index 0000000000..b65d3e7449 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/modbus-version-mapping.util.ts @@ -0,0 +1,77 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { + ModbusDataType, + ModbusLegacyRegisterValues, + ModbusLegacySlave, + ModbusMasterConfig, + ModbusRegisterValues, + ModbusSlave, ModbusValue, ModbusValues, + SlaveConfig +} from '@home/components/widget/lib/gateway/gateway-widget.models'; + +export class ModbusVersionMappingUtil { + static mapMasterToUpgradedVersion(master: ModbusMasterConfig): ModbusMasterConfig { + return { + slaves: master.slaves.map((slave: SlaveConfig) => ({ + ...slave, + deviceType: slave.deviceType ?? 'default', + })) + }; + } + + static mapSlaveToDowngradedVersion(slave: ModbusSlave): ModbusLegacySlave { + const values = Object.keys(slave.values).reduce((acc, valueKey) => { + acc = { + ...acc, + [valueKey]: [ + slave.values[valueKey] + ] + }; + return acc; + }, {} as ModbusLegacyRegisterValues); + return { + ...slave, + values + }; + } + + static mapSlaveToUpgradedVersion(slave: ModbusLegacySlave): ModbusSlave { + const values = Object.keys(slave.values).reduce((acc, valueKey) => { + acc = { + ...acc, + [valueKey]: this.mapValuesToUpgradedVersion(slave.values[valueKey][0]) + }; + return acc; + }, {} as ModbusRegisterValues); + return { + ...slave, + values + }; + } + + private static mapValuesToUpgradedVersion(registerValues: ModbusValues): ModbusValues { + return Object.keys(registerValues).reduce((acc, valueKey) => { + acc = { + ...acc, + [valueKey]: registerValues[valueKey].map((value: ModbusValue) => + ({ ...value, type: (value.type as string) === 'int' ? ModbusDataType.INT16 : value.type })) + }; + return acc; + }, {} as ModbusValues); + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts new file mode 100644 index 0000000000..56eea67ddf --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts @@ -0,0 +1,113 @@ +/// +/// Copyright © 2016-2024 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { + DeviceConnectorMapping, + LegacyDeviceConnectorMapping, + LegacyServerConfig, + OPCBasicConfig_v3_5_2, + ServerConfig +} from '@home/components/widget/lib/gateway/gateway-widget.models'; + +export class OpcVersionMappingUtil { + static mapServerToUpgradedVersion(server: LegacyServerConfig): ServerConfig { + const { mapping, disableSubscriptions, ...restServer } = server; + return { + ...restServer, + enableSubscriptions: !disableSubscriptions, + }; + } + + static mapServerToDowngradedVersion(config: OPCBasicConfig_v3_5_2): LegacyServerConfig { + const { mapping, server } = config; + const { enableSubscriptions, ...restServer } = server; + return { + ...restServer, + mapping: mapping ? this.mapMappingToDowngradedVersion(mapping) : [], + disableSubscriptions: !enableSubscriptions, + }; + } + + static mapMappingToUpgradedVersion(mapping: LegacyDeviceConnectorMapping[]): DeviceConnectorMapping[] { + return mapping?.map((oldMapping: any) => ({ + ...oldMapping, + deviceNodeSource: 'path', + deviceInfo: { + deviceNameExpression: oldMapping.deviceNamePattern, + deviceNameExpressionSource: 'path', + deviceProfileExpression: oldMapping.deviceTypePattern ?? 'default', + deviceProfileExpressionSource: 'path', + }, + attributes: oldMapping.attributes.map(attribute => ({ + key: attribute.key, + type: 'path', + value: attribute.path, + })), + attributes_updates: oldMapping.attributes_updates.map(attributeUpdate => ({ + key: attributeUpdate.attributeOnThingsBoard, + type: 'path', + value: attributeUpdate.attributeOnDevice, + })), + timeseries: oldMapping.timeseries.map(timeseries => ({ + key: timeseries.key, + type: 'path', + value: timeseries.path, + })), + rpc_methods: oldMapping.rpc_methods.map(rpcMethod => ({ + method: rpcMethod.method, + arguments: rpcMethod.arguments.map(arg => ({ + value: arg, + type: this.getArgumentType(arg), + })) + })) + })); + } + + static mapMappingToDowngradedVersion(mapping: DeviceConnectorMapping[]): LegacyDeviceConnectorMapping[] { + return mapping?.map((newMapping: DeviceConnectorMapping) => ({ + ...newMapping, + deviceNamePattern: newMapping.deviceInfo.deviceNameExpression, + deviceTypePattern: newMapping.deviceInfo.deviceProfileExpression, + attributes: newMapping.attributes.map((attribute: any) => ({ + key: attribute.key, + path: attribute.value, + })), + attributes_updates: newMapping.attributes_updates.map((attributeUpdate: any) => ({ + attributeOnThingsBoard: attributeUpdate.key, + attributeOnDevice: attributeUpdate.value, + })), + timeseries: newMapping.timeseries.map((timeseries: any) => ({ + key: timeseries.key, + path: timeseries.value, + })), + rpc_methods: newMapping.rpc_methods.map((rpcMethod: any) => ({ + method: rpcMethod.method, + arguments: rpcMethod.arguments.map((arg: any) => arg.value) + })) + })); + } + + private static getArgumentType(arg: unknown): string { + switch (typeof arg) { + case 'boolean': + return 'boolean'; + case 'number': + return Number.isInteger(arg) ? 'integer' : 'float'; + default: + return 'string'; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts index b3663c9b48..f241bc91d0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts @@ -116,10 +116,10 @@ import { } from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/broker-config-control/broker-config-control.component'; import { WorkersConfigControlComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/workers-config-control/workers-config-control.component'; +} from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/workers-config-control/workers-config-control.component'; import { OpcServerConfigComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component'; +} from '@home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component'; import { MqttBasicConfigComponent } from '@home/components/widget/lib/gateway/connectors-configuration/mqtt/basic-config/mqtt-basic-config.component'; @@ -128,7 +128,7 @@ import { } from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; import { OpcUaBasicConfigComponent -} from '@home/components/widget/lib/gateway/connectors-configuration/opc-ua-basic-config/opc-ua-basic-config.component'; +} from '@home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component'; import { ModbusBasicConfigComponent } from '@home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component'; @@ -154,6 +154,12 @@ import { import { GatewayAdvancedConfigurationComponent } from '@home/components/widget/lib/gateway/configuration/advanced/gateway-advanced-configuration.component'; +import { + OpcUaLegacyBasicConfigComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-legacy-basic-config.component'; +import { + ModbusLegacyBasicConfigComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-legacy-basic-config.component'; @NgModule({ declarations: [ @@ -245,6 +251,8 @@ import { MqttLegacyBasicConfigComponent, GatewayBasicConfigurationComponent, GatewayAdvancedConfigurationComponent, + OpcUaLegacyBasicConfigComponent, + ModbusLegacyBasicConfigComponent, ], exports: [ EntitiesTableWidgetComponent, diff --git a/ui-ngx/src/assets/metadata/connector-default-configs/modbus.json b/ui-ngx/src/assets/metadata/connector-default-configs/modbus.json index 441f63ab5f..96fb59dcf5 100644 --- a/ui-ngx/src/assets/metadata/connector-default-configs/modbus.json +++ b/ui-ngx/src/assets/metadata/connector-default-configs/modbus.json @@ -1,246 +1,474 @@ { - "master": { - "slaves": [ - { - "name": "Slave 1", - "host": "127.0.0.1", - "port": 5021, - "type": "tcp", - "method": "socket", - "timeout": 35, - "byteOrder": "LITTLE", - "wordOrder": "LITTLE", - "retries": true, - "retryOnEmpty": true, - "retryOnInvalid": true, - "pollPeriod": 5000, - "unitId": 1, - "deviceName": "Temp Sensor", - "deviceType": "default", - "sendDataOnlyOnChange": true, - "connectAttemptTimeMs": 5000, - "connectAttemptCount": 5, - "waitAfterFailedAttemptsMs": 300000, - "attributes": [ - { - "tag": "string_read", - "type": "string", - "functionCode": 4, - "objectsCount": 4, - "address": 1 - }, - { - "tag": "bits_read", - "type": "bits", - "functionCode": 4, - "objectsCount": 1, - "address": 5 - }, - { - "tag": "8int_read", - "type": "8int", - "functionCode": 4, - "objectsCount": 1, - "address": 6 - }, - { - "tag": "16int_read", - "type": "16int", - "functionCode": 4, - "objectsCount": 1, - "address": 7 - }, - { - "tag": "32int_read_divider", - "type": "32int", - "functionCode": 4, - "objectsCount": 2, - "address": 8, - "divider": 10 - }, - { - "tag": "8int_read_multiplier", - "type": "8int", - "functionCode": 4, - "objectsCount": 1, - "address": 10, - "multiplier": 10 - }, - { - "tag": "32int_read", - "type": "32int", - "functionCode": 4, - "objectsCount": 2, - "address": 11 - }, - { - "tag": "64int_read", - "type": "64int", - "functionCode": 4, - "objectsCount": 4, - "address": 13 - } - ], - "timeseries": [ - { - "tag": "8uint_read", - "type": "8uint", - "functionCode": 4, - "objectsCount": 1, - "address": 17 - }, - { - "tag": "16uint_read", - "type": "16uint", - "functionCode": 4, - "objectsCount": 2, - "address": 18 - }, - { - "tag": "32uint_read", - "type": "32uint", - "functionCode": 4, - "objectsCount": 4, - "address": 20 - }, - { - "tag": "64uint_read", - "type": "64uint", - "functionCode": 4, - "objectsCount": 1, - "address": 24 - }, - { - "tag": "16float_read", - "type": "16float", - "functionCode": 4, - "objectsCount": 1, - "address": 25 - }, - { - "tag": "32float_read", - "type": "32float", - "functionCode": 4, - "objectsCount": 2, - "address": 26 - }, - { - "tag": "64float_read", - "type": "64float", - "functionCode": 4, - "objectsCount": 4, - "address": 28 - } - ], - "attributeUpdates": [ - { - "tag": "shared_attribute_write", - "type": "32int", - "functionCode": 6, - "objectsCount": 2, - "address": 29 - } - ], - "rpc": [ - { - "tag": "setValue", - "type": "bits", - "functionCode": 5, - "objectsCount": 1, - "address": 31 - }, - { - "tag": "getValue", - "type": "bits", - "functionCode": 1, - "objectsCount": 1, - "address": 31 - }, - { - "tag": "setCPUFanSpeed", - "type": "32int", - "functionCode": 16, - "objectsCount": 2, - "address": 33 - }, - { - "tag": "getCPULoad", - "type": "32int", - "functionCode": 4, - "objectsCount": 2, - "address": 35 - } - ] - } - ] - }, - "slave": { - "type": "tcp", - "host": "127.0.0.1", - "port": 5026, - "method": "socket", - "deviceName": "Modbus Slave Example", - "deviceType": "default", - "pollPeriod": 5000, - "sendDataToThingsBoard": false, - "byteOrder": "LITTLE", - "wordOrder": "LITTLE", - "unitId": 0, - "values": { - "holding_registers": { - "attributes": [ + "3.5.1": { + "master": { + "slaves": [ { - "address": 1, - "type": "string", - "tag": "sm", - "objectsCount": 1, - "value": "ON" + "name": "Slave 1", + "host": "127.0.0.1", + "port": 5021, + "type": "tcp", + "method": "socket", + "timeout": 35, + "byteOrder": "LITTLE", + "wordOrder": "LITTLE", + "retries": true, + "retryOnEmpty": true, + "retryOnInvalid": true, + "pollPeriod": 5000, + "unitId": 1, + "deviceName": "Temp Sensor", + "deviceType": "default", + "sendDataOnlyOnChange": true, + "connectAttemptTimeMs": 5000, + "connectAttemptCount": 5, + "waitAfterFailedAttemptsMs": 300000, + "attributes": [ + { + "tag": "string_read", + "type": "string", + "functionCode": 4, + "objectsCount": 4, + "address": 1 + }, + { + "tag": "bits_read", + "type": "bits", + "functionCode": 4, + "objectsCount": 1, + "address": 5 + }, + { + "tag": "8int_read", + "type": "8int", + "functionCode": 4, + "objectsCount": 1, + "address": 6 + }, + { + "tag": "16int_read", + "type": "16int", + "functionCode": 4, + "objectsCount": 1, + "address": 7 + }, + { + "tag": "32int_read_divider", + "type": "32int", + "functionCode": 4, + "objectsCount": 2, + "address": 8, + "divider": 10 + }, + { + "tag": "8int_read_multiplier", + "type": "8int", + "functionCode": 4, + "objectsCount": 1, + "address": 10, + "multiplier": 10 + }, + { + "tag": "32int_read", + "type": "32int", + "functionCode": 4, + "objectsCount": 2, + "address": 11 + }, + { + "tag": "64int_read", + "type": "64int", + "functionCode": 4, + "objectsCount": 4, + "address": 13 + } + ], + "timeseries": [ + { + "tag": "8uint_read", + "type": "8uint", + "functionCode": 4, + "objectsCount": 1, + "address": 17 + }, + { + "tag": "16uint_read", + "type": "16uint", + "functionCode": 4, + "objectsCount": 2, + "address": 18 + }, + { + "tag": "32uint_read", + "type": "32uint", + "functionCode": 4, + "objectsCount": 4, + "address": 20 + }, + { + "tag": "64uint_read", + "type": "64uint", + "functionCode": 4, + "objectsCount": 1, + "address": 24 + }, + { + "tag": "16float_read", + "type": "16float", + "functionCode": 4, + "objectsCount": 1, + "address": 25 + }, + { + "tag": "32float_read", + "type": "32float", + "functionCode": 4, + "objectsCount": 2, + "address": 26 + }, + { + "tag": "64float_read", + "type": "64float", + "functionCode": 4, + "objectsCount": 4, + "address": 28 + } + ], + "attributeUpdates": [ + { + "tag": "shared_attribute_write", + "type": "32int", + "functionCode": 6, + "objectsCount": 2, + "address": 29 + } + ], + "rpc": [ + { + "tag": "setValue", + "type": "bits", + "functionCode": 5, + "objectsCount": 1, + "address": 31 + }, + { + "tag": "getValue", + "type": "bits", + "functionCode": 1, + "objectsCount": 1, + "address": 31 + }, + { + "tag": "setCPUFanSpeed", + "type": "32int", + "functionCode": 16, + "objectsCount": 2, + "address": 33 + }, + { + "tag": "getCPULoad", + "type": "32int", + "functionCode": 4, + "objectsCount": 2, + "address": 35 + } + ] } - ], - "timeseries": [ - { - "address": 2, - "type": "8int", - "tag": "smm", - "objectsCount": 1, - "value": "12334" - } - ], - "attributeUpdates": [ - { - "tag": "shared_attribute_write", - "type": "32int", - "functionCode": 6, - "objectsCount": 2, - "address": 29, - "value": 1243 + ] + }, + "slave": { + "type": "tcp", + "host": "127.0.0.1", + "port": 5026, + "method": "socket", + "deviceName": "Modbus Slave Example", + "deviceType": "default", + "pollPeriod": 5000, + "sendDataToThingsBoard": false, + "byteOrder": "LITTLE", + "wordOrder": "LITTLE", + "unitId": 0, + "values": { + "holding_registers": { + "attributes": [ + { + "address": 1, + "type": "string", + "tag": "sm", + "objectsCount": 1, + "value": "ON" + } + ], + "timeseries": [ + { + "address": 2, + "type": "8int", + "tag": "smm", + "objectsCount": 1, + "value": "12334" + } + ], + "attributeUpdates": [ + { + "tag": "shared_attribute_write", + "type": "32int", + "functionCode": 6, + "objectsCount": 2, + "address": 29, + "value": 1243 + } + ], + "rpc": [ + { + "tag": "setValue", + "type": "bits", + "functionCode": 5, + "objectsCount": 1, + "address": 31, + "value": 22 + } + ] + }, + "coils_initializer": { + "attributes": [ + { + "address": 5, + "type": "string", + "tag": "sm", + "objectsCount": 1, + "value": "12" + } + ], + "timeseries": [], + "attributeUpdates": [], + "rpc": [] } - ], - "rpc": [ + } + } + }, + "legacy": { + "master": { + "slaves": [ { - "tag": "setValue", - "type": "bits", - "functionCode": 5, - "objectsCount": 1, - "address": 31, - "value": 22 + "host": "127.0.0.1", + "port": 5021, + "type": "tcp", + "method": "socket", + "timeout": 35, + "byteOrder": "LITTLE", + "wordOrder": "LITTLE", + "retries": true, + "retryOnEmpty": true, + "retryOnInvalid": true, + "pollPeriod": 5000, + "unitId": 1, + "deviceName": "Temp Sensor", + "sendDataOnlyOnChange": true, + "connectAttemptTimeMs": 5000, + "connectAttemptCount": 5, + "waitAfterFailedAttemptsMs": 300000, + "attributes": [ + { + "tag": "string_read", + "type": "string", + "functionCode": 4, + "objectsCount": 4, + "address": 1 + }, + { + "tag": "bits_read", + "type": "bits", + "functionCode": 4, + "objectsCount": 1, + "address": 5 + }, + { + "tag": "16int_read", + "type": "16int", + "functionCode": 4, + "objectsCount": 1, + "address": 7 + }, + { + "tag": "32int_read_divider", + "type": "32int", + "functionCode": 4, + "objectsCount": 2, + "address": 8, + "divider": 10 + }, + { + "tag": "32int_read", + "type": "32int", + "functionCode": 4, + "objectsCount": 2, + "address": 11 + }, + { + "tag": "64int_read", + "type": "64int", + "functionCode": 4, + "objectsCount": 4, + "address": 13 + } + ], + "timeseries": [ + { + "tag": "16uint_read", + "type": "16uint", + "functionCode": 4, + "objectsCount": 2, + "address": 18 + }, + { + "tag": "32uint_read", + "type": "32uint", + "functionCode": 4, + "objectsCount": 4, + "address": 20 + }, + { + "tag": "64uint_read", + "type": "64uint", + "functionCode": 4, + "objectsCount": 1, + "address": 24 + }, + { + "tag": "16float_read", + "type": "16float", + "functionCode": 4, + "objectsCount": 1, + "address": 25 + }, + { + "tag": "32float_read", + "type": "32float", + "functionCode": 4, + "objectsCount": 2, + "address": 26 + }, + { + "tag": "64float_read", + "type": "64float", + "functionCode": 4, + "objectsCount": 4, + "address": 28 + } + ], + "attributeUpdates": [ + { + "tag": "shared_attribute_write", + "type": "32int", + "functionCode": 6, + "objectsCount": 2, + "address": 29 + } + ], + "rpc": [ + { + "tag": "setValue", + "type": "bits", + "functionCode": 5, + "objectsCount": 1, + "address": 31 + }, + { + "tag": "getValue", + "type": "bits", + "functionCode": 1, + "objectsCount": 1, + "address": 31 + }, + { + "tag": "setCPUFanSpeed", + "type": "32int", + "functionCode": 16, + "objectsCount": 2, + "address": 33 + }, + { + "tag": "getCPULoad", + "type": "32int", + "functionCode": 4, + "objectsCount": 2, + "address": 35 + } + ] } ] }, - "coils_initializer": { - "attributes": [ - { - "address": 5, - "type": "string", - "tag": "sm", - "objectsCount": 1, - "value": "12" - } - ], - "timeseries": [], - "attributeUpdates": [], - "rpc": [] + "slave": { + "type": "tcp", + "host": "127.0.0.1", + "port": 5026, + "method": "socket", + "deviceName": "Modbus Slave Example", + "deviceType": "default", + "pollPeriod": 5000, + "sendDataToThingsBoard": false, + "byteOrder": "LITTLE", + "wordOrder": "LITTLE", + "unitId": 0, + "values": { + "holding_registers": [ + { + "attributes": [ + { + "address": 1, + "type": "string", + "tag": "sm", + "objectsCount": 1, + "value": "ON" + } + ], + "timeseries": [ + { + "address": 2, + "type": "int", + "tag": "smm", + "objectsCount": 1, + "value": "12334" + } + ], + "attributeUpdates": [ + { + "tag": "shared_attribute_write", + "type": "32int", + "functionCode": 6, + "objectsCount": 2, + "address": 29, + "value": 1243 + } + ], + "rpc": [ + { + "tag": "setValue", + "type": "bits", + "functionCode": 5, + "objectsCount": 1, + "address": 31, + "value": 22 + } + ] + } + ], + "coils_initializer": [ + { + "attributes": [ + { + "address": 5, + "type": "string", + "tag": "sm", + "objectsCount": 1, + "value": "12" + } + ], + "timeseries": [], + "attributeUpdates": [], + "rpc": [] + } + ] + } } } - } } diff --git a/ui-ngx/src/assets/metadata/connector-default-configs/opcua.json b/ui-ngx/src/assets/metadata/connector-default-configs/opcua.json index 7ff5b78433..eb33f9235e 100644 --- a/ui-ngx/src/assets/metadata/connector-default-configs/opcua.json +++ b/ui-ngx/src/assets/metadata/connector-default-configs/opcua.json @@ -1,66 +1,120 @@ { - "server": { - "url": "localhost:4840/freeopcua/server/", - "timeoutInMillis": 5000, - "scanPeriodInMillis": 3600000, - "pollPeriodInMillis": 5000, - "enableSubscriptions": true, - "subCheckPeriodInMillis": 100, - "showMap": false, - "security": "Basic128Rsa15", - "identity": { - "type": "anonymous" - } - }, - "mapping": [{ - "deviceNodePattern": "Root\\.Objects\\.Device1", - "deviceNodeSource": "path", - "deviceInfo": { - "deviceNameExpression": "Device ${Root\\.Objects\\.Device1\\.serialNumber}", - "deviceNameExpressionSource": "path", - "deviceProfileExpression": "Device", - "deviceProfileExpressionSource": "constant" + "3.5.1": { + "server": { + "url": "localhost:4840/freeopcua/server/", + "timeoutInMillis": 5000, + "scanPeriodInMillis": 3600000, + "pollPeriodInMillis": 5000, + "enableSubscriptions": true, + "subCheckPeriodInMillis": 100, + "showMap": false, + "security": "Basic128Rsa15", + "identity": { + "type": "anonymous" + } + }, + "mapping": [{ + "deviceNodePattern": "Root\\.Objects\\.Device1", + "deviceNodeSource": "path", + "deviceInfo": { + "deviceNameExpression": "Device ${Root\\.Objects\\.Device1\\.serialNumber}", + "deviceNameExpressionSource": "path", + "deviceProfileExpression": "Device", + "deviceProfileExpressionSource": "constant" + }, + "attributes": [ + { + "key": "temperature °C", + "type": "path", + "value": "${ns=2;i=5}" + } + ], + "timeseries": [ + { + "key": "humidity", + "type": "path", + "value": "${Root\\.Objects\\.Device1\\.TemperatureAndHumiditySensor\\.Humidity}" + }, + { + "key": "batteryLevel", + "type": "path", + "value": "${Battery\\.batteryLevel}" + } + ], + "rpc_methods": [ + { + "method": "multiply", + "arguments": [ + { + "type": "integer", + "value": 2 + }, + { + "type": "integer", + "value": 4 + } + ] + } + ], + "attributes_updates": [ + { + "key": "deviceName", + "type": "path", + "value": "Root\\.Objects\\.Device1\\.serialNumber" + } + ] + }] }, - "attributes": [ - { - "key": "temperature °C", - "type": "path", - "value": "${ns=2;i=5}" - } - ], - "timeseries": [ - { - "key": "humidity", - "type": "path", - "value": "${Root\\.Objects\\.Device1\\.TemperatureAndHumiditySensor\\.Humidity}" - }, - { - "key": "batteryLevel", - "type": "path", - "value": "${Battery\\.batteryLevel}" - } - ], - "rpc_methods": [ - { - "method": "multiply", - "arguments": [ - { - "type": "integer", - "value": 2 - }, - { - "type": "integer", - "value": 4 - } - ] - } - ], - "attributes_updates": [ - { - "key": "deviceName", - "type": "path", - "value": "Root\\.Objects\\.Device1\\.serialNumber" - } - ] - }] + "legacy": { + "server": { + "name": "OPC-UA Default Server", + "url": "localhost:4840/freeopcua/server/", + "timeoutInMillis": 5000, + "scanPeriodInMillis": 5000, + "disableSubscriptions": false, + "subCheckPeriodInMillis": 100, + "showMap": false, + "security": "Basic128Rsa15", + "identity": { + "type": "anonymous" + }, + "mapping": [ + { + "deviceNodePattern": "Root\\.Objects\\.Device1", + "deviceNamePattern": "Device ${Root\\.Objects\\.Device1\\.serialNumber}", + "attributes": [ + { + "key": "temperature °C", + "path": "${ns=2;i=5}" + } + ], + "timeseries": [ + { + "key": "humidity", + "path": "${Root\\.Objects\\.Device1\\.TemperatureAndHumiditySensor\\.Humidity}" + }, + { + "key": "batteryLevel", + "path": "${Battery\\.batteryLevel}" + } + ], + "rpc_methods": [ + { + "method": "multiply", + "arguments": [ + 2, + 4 + ] + } + ], + "attributes_updates": [ + { + "attributeOnThingsBoard": "deviceName", + "attributeOnDevice": "Root\\.Objects\\.Device1\\.serialNumber" + } + ] + } + ] + } + } } From 5329fe3aa18a8ca386f0114171242e1ec147afde Mon Sep 17 00:00:00 2001 From: mpetrov <mpetrov@thingsboard.io> Date: Tue, 10 Sep 2024 19:18:21 +0300 Subject: [PATCH 65/80] [4114] Adjusted OPC mapping --- .../lib/gateway/gateway-widget.models.ts | 9 +-- .../gateway/utils/opc-version-mapping.util.ts | 70 ++++++++++++------- 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 8a0e4005fd..b933ff1186 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -265,9 +265,9 @@ export interface WorkersConfig { export interface ConnectorDeviceInfo { deviceNameExpression: string; - deviceNameExpressionSource: SourceType; + deviceNameExpressionSource: SourceType | OPCUaSourceType; deviceProfileExpression: string; - deviceProfileExpressionSource: SourceType; + deviceProfileExpressionSource: SourceType | OPCUaSourceType; } export interface Attribute { @@ -292,7 +292,7 @@ export interface LegacyTimeseries { path: string; } -interface RpcArgument { +export interface RpcArgument { type: string; value: number; } @@ -363,7 +363,7 @@ export type ConverterMappingFormValue = Omit<ConverterConnectorMapping, 'convert export interface DeviceConnectorMapping { deviceNodePattern: string; - deviceNodeSource: SourceType; + deviceNodeSource: OPCUaSourceType; deviceInfo: ConnectorDeviceInfo; attributes?: Attribute[]; timeseries?: Timeseries[]; @@ -373,6 +373,7 @@ export interface DeviceConnectorMapping { export interface LegacyDeviceConnectorMapping { deviceNamePattern: string; + deviceNodePattern: string; deviceTypePattern: string; attributes?: LegacyAttribute[]; timeseries?: LegacyTimeseries[]; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts index 56eea67ddf..161eaf7daa 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts @@ -15,11 +15,21 @@ /// import { + Attribute, + AttributesUpdate, DeviceConnectorMapping, + LegacyAttribute, + LegacyDeviceAttributeUpdate, LegacyDeviceConnectorMapping, + LegacyRpcMethod, LegacyServerConfig, + LegacyTimeseries, OPCBasicConfig_v3_5_2, - ServerConfig + OPCUaSourceType, + RpcArgument, + RpcMethod, + ServerConfig, + Timeseries } from '@home/components/widget/lib/gateway/gateway-widget.models'; export class OpcVersionMappingUtil { @@ -42,64 +52,74 @@ export class OpcVersionMappingUtil { } static mapMappingToUpgradedVersion(mapping: LegacyDeviceConnectorMapping[]): DeviceConnectorMapping[] { - return mapping?.map((oldMapping: any) => ({ - ...oldMapping, - deviceNodeSource: 'path', + return mapping.map((legacyMapping: LegacyDeviceConnectorMapping) => ({ + ...legacyMapping, + deviceNodeSource: this.getTypeSourceByValue(legacyMapping.deviceNodePattern), deviceInfo: { - deviceNameExpression: oldMapping.deviceNamePattern, - deviceNameExpressionSource: 'path', - deviceProfileExpression: oldMapping.deviceTypePattern ?? 'default', - deviceProfileExpressionSource: 'path', + deviceNameExpression: legacyMapping.deviceNamePattern, + deviceNameExpressionSource: this.getTypeSourceByValue(legacyMapping.deviceNamePattern), + deviceProfileExpression: legacyMapping.deviceTypePattern ?? 'default', + deviceProfileExpressionSource: this.getTypeSourceByValue(legacyMapping.deviceTypePattern ?? 'default'), }, - attributes: oldMapping.attributes.map(attribute => ({ + attributes: legacyMapping.attributes.map((attribute: LegacyAttribute) => ({ key: attribute.key, - type: 'path', + type: this.getTypeSourceByValue(attribute.path), value: attribute.path, })), - attributes_updates: oldMapping.attributes_updates.map(attributeUpdate => ({ + attributes_updates: legacyMapping.attributes_updates.map((attributeUpdate: LegacyDeviceAttributeUpdate) => ({ key: attributeUpdate.attributeOnThingsBoard, - type: 'path', + type: this.getTypeSourceByValue(attributeUpdate.attributeOnDevice), value: attributeUpdate.attributeOnDevice, })), - timeseries: oldMapping.timeseries.map(timeseries => ({ + timeseries: legacyMapping.timeseries.map((timeseries: LegacyTimeseries) => ({ key: timeseries.key, - type: 'path', + type: this.getTypeSourceByValue(timeseries.path), value: timeseries.path, })), - rpc_methods: oldMapping.rpc_methods.map(rpcMethod => ({ + rpc_methods: legacyMapping.rpc_methods.map((rpcMethod: LegacyRpcMethod) => ({ method: rpcMethod.method, arguments: rpcMethod.arguments.map(arg => ({ value: arg, type: this.getArgumentType(arg), - })) + } as RpcArgument)) })) })); } static mapMappingToDowngradedVersion(mapping: DeviceConnectorMapping[]): LegacyDeviceConnectorMapping[] { - return mapping?.map((newMapping: DeviceConnectorMapping) => ({ - ...newMapping, - deviceNamePattern: newMapping.deviceInfo.deviceNameExpression, - deviceTypePattern: newMapping.deviceInfo.deviceProfileExpression, - attributes: newMapping.attributes.map((attribute: any) => ({ + return mapping.map((upgradedMapping: DeviceConnectorMapping) => ({ + ...upgradedMapping, + deviceNamePattern: upgradedMapping.deviceInfo.deviceNameExpression, + deviceTypePattern: upgradedMapping.deviceInfo.deviceProfileExpression, + attributes: upgradedMapping.attributes.map((attribute: Attribute) => ({ key: attribute.key, path: attribute.value, })), - attributes_updates: newMapping.attributes_updates.map((attributeUpdate: any) => ({ + attributes_updates: upgradedMapping.attributes_updates.map((attributeUpdate: AttributesUpdate) => ({ attributeOnThingsBoard: attributeUpdate.key, attributeOnDevice: attributeUpdate.value, })), - timeseries: newMapping.timeseries.map((timeseries: any) => ({ + timeseries: upgradedMapping.timeseries.map((timeseries: Timeseries) => ({ key: timeseries.key, path: timeseries.value, })), - rpc_methods: newMapping.rpc_methods.map((rpcMethod: any) => ({ + rpc_methods: upgradedMapping.rpc_methods.map((rpcMethod: RpcMethod) => ({ method: rpcMethod.method, - arguments: rpcMethod.arguments.map((arg: any) => arg.value) + arguments: rpcMethod.arguments.map((arg: RpcArgument) => arg.value) })) })); } + private static getTypeSourceByValue(value: string): OPCUaSourceType { + if (value.includes('${')) { + return OPCUaSourceType.IDENTIFIER; + } + if (value.includes(`/`) || value.includes('\\')) { + return OPCUaSourceType.PATH; + } + return OPCUaSourceType.CONST; + } + private static getArgumentType(arg: unknown): string { switch (typeof arg) { case 'boolean': From 6104778cd24c1a767cd0193bf689a757b4fc03c7 Mon Sep 17 00:00:00 2001 From: mpetrov <mpetrov@thingsboard.io> Date: Tue, 10 Sep 2024 19:34:03 +0300 Subject: [PATCH 66/80] [4114] refactoring --- .../gateway/abstract/modbus-version-processor.abstract.ts | 1 + .../lib/gateway/abstract/mqtt-version-processor.abstract.ts | 2 ++ .../lib/gateway/abstract/opc-version-processor.abstract.ts | 1 + .../widget/lib/gateway/gateway-connectors.component.ts | 4 ++++ .../widget/lib/gateway/utils/modbus-version-mapping.util.ts | 5 ++++- .../widget/lib/gateway/utils/opc-version-mapping.util.ts | 1 + 6 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts index d520a5b1e8..abcf6ce597 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts @@ -34,6 +34,7 @@ export class ModbusVersionProcessor extends GatewayConnectorVersionProcessor<any ) { super(gatewayVersionStr, connector); } + getUpgradedVersion(): GatewayConnector<ModbusBasicConfig_v3_5_2> { const configurationJson = this.connector.configurationJson; return { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts index 645eb64fa4..f55269eadf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts @@ -27,6 +27,7 @@ import { MqttVersionMappingUtil } from '../utils/mqtt-version-mapping.util'; import { GatewayConnectorVersionProcessor } from './gateway-connector-version-processor.abstract'; export class MqttVersionProcessor extends GatewayConnectorVersionProcessor<MQTTBasicConfig> { + private readonly mqttRequestTypeKeys = Object.values(RequestType); constructor( @@ -35,6 +36,7 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor<MQTTB ) { super(gatewayVersionStr, connector); } + getUpgradedVersion(): GatewayConnector<MQTTBasicConfig_v3_5_2> { const { connectRequests, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts index 11c9908058..e0337d9fe3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts @@ -31,6 +31,7 @@ export class OpcVersionProcessor extends GatewayConnectorVersionProcessor<OPCBas ) { super(gatewayVersionStr, connector); } + getUpgradedVersion(): GatewayConnector<OPCBasicConfig_v3_5_2> { const server = this.connector.configurationJson.server as LegacyServerConfig; return { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index 9be5b550ce..03765613da 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -245,6 +245,10 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie delete value.class; } + if (this.gatewayVersion && !value.configVersion) { + value.configVersion = this.gatewayVersion; + } + value.ts = Date.now(); return value; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/modbus-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/modbus-version-mapping.util.ts index b65d3e7449..fbb78059e1 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/modbus-version-mapping.util.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/modbus-version-mapping.util.ts @@ -20,11 +20,14 @@ import { ModbusLegacySlave, ModbusMasterConfig, ModbusRegisterValues, - ModbusSlave, ModbusValue, ModbusValues, + ModbusSlave, + ModbusValue, + ModbusValues, SlaveConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; export class ModbusVersionMappingUtil { + static mapMasterToUpgradedVersion(master: ModbusMasterConfig): ModbusMasterConfig { return { slaves: master.slaves.map((slave: SlaveConfig) => ({ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts index 161eaf7daa..35807065e9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/utils/opc-version-mapping.util.ts @@ -33,6 +33,7 @@ import { } from '@home/components/widget/lib/gateway/gateway-widget.models'; export class OpcVersionMappingUtil { + static mapServerToUpgradedVersion(server: LegacyServerConfig): ServerConfig { const { mapping, disableSubscriptions, ...restServer } = server; return { From 23bf12e41c0d481ccd5e9baa11bdc62e5b181659 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko <vprykhodko@thingsboard.io> Date: Wed, 11 Sep 2024 10:53:23 +0300 Subject: [PATCH 67/80] UI: Change link for entity view documentation --- ui-ngx/src/app/shared/models/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/shared/models/constants.ts b/ui-ngx/src/app/shared/models/constants.ts index 829e49257f..b43081c6e8 100644 --- a/ui-ngx/src/app/shared/models/constants.ts +++ b/ui-ngx/src/app/shared/models/constants.ts @@ -161,7 +161,7 @@ export const HelpLinks = { assetProfiles: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/ui/asset-profiles`, edges: `${helpBaseUrl}/docs/edge/getting-started-guides/what-is-edge`, assets: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/ui/assets`, - entityViews: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/ui/entity-views`, + entityViews: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/entity-views`, entitiesImport: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/bulk-provisioning`, rulechains: `${helpBaseUrl}/docs${docPlatformPrefix}/user-guide/ui/rule-chains`, lwm2mResourceLibrary: `${helpBaseUrl}/docs${docPlatformPrefix}/reference/lwm2m-api`, From e4450b8925d2e6c06dbc4b8e077bb946e0efab4a Mon Sep 17 00:00:00 2001 From: YevhenBondarenko <ybondarenko@thingsboard.io> Date: Wed, 11 Sep 2024 10:44:53 +0200 Subject: [PATCH 68/80] fixed concurrnet modification during printStats --- .../DefaultTbEntityDataSubscriptionService.java | 10 +++++----- .../DefaultTbLocalSubscriptionService.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java index 632ea44940..019b6eb5e8 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbEntityDataSubscriptionService.java @@ -94,7 +94,7 @@ import java.util.stream.Collectors; public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubscriptionService { private static final int DEFAULT_LIMIT = 100; - private final Map<String, Map<Integer, TbAbstractSubCtx>> subscriptionsBySessionId = new ConcurrentHashMap<>(); + private final ConcurrentMap<String, ConcurrentMap<Integer, TbAbstractSubCtx>> subscriptionsBySessionId = new ConcurrentHashMap<>(); @Autowired @Lazy @@ -495,7 +495,7 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc } private TbEntityDataSubCtx createSubCtx(WebSocketSessionRef sessionRef, EntityDataCmd cmd) { - Map<Integer, TbAbstractSubCtx> sessionSubs = subscriptionsBySessionId.computeIfAbsent(sessionRef.getSessionId(), k -> new HashMap<>()); + Map<Integer, TbAbstractSubCtx> sessionSubs = subscriptionsBySessionId.computeIfAbsent(sessionRef.getSessionId(), k -> new ConcurrentHashMap<>()); TbEntityDataSubCtx ctx = new TbEntityDataSubCtx(serviceId, wsService, entityService, localSubscriptionService, attributesService, stats, sessionRef, cmd.getCmdId(), maxEntitiesPerDataSubscription); if (cmd.getQuery() != null) { @@ -506,7 +506,7 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc } private TbEntityCountSubCtx createSubCtx(WebSocketSessionRef sessionRef, EntityCountCmd cmd) { - Map<Integer, TbAbstractSubCtx> sessionSubs = subscriptionsBySessionId.computeIfAbsent(sessionRef.getSessionId(), k -> new HashMap<>()); + Map<Integer, TbAbstractSubCtx> sessionSubs = subscriptionsBySessionId.computeIfAbsent(sessionRef.getSessionId(), k -> new ConcurrentHashMap<>()); TbEntityCountSubCtx ctx = new TbEntityCountSubCtx(serviceId, wsService, entityService, localSubscriptionService, attributesService, stats, sessionRef, cmd.getCmdId()); if (cmd.getQuery() != null) { @@ -518,7 +518,7 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc private TbAlarmDataSubCtx createSubCtx(WebSocketSessionRef sessionRef, AlarmDataCmd cmd) { - Map<Integer, TbAbstractSubCtx> sessionSubs = subscriptionsBySessionId.computeIfAbsent(sessionRef.getSessionId(), k -> new HashMap<>()); + Map<Integer, TbAbstractSubCtx> sessionSubs = subscriptionsBySessionId.computeIfAbsent(sessionRef.getSessionId(), k -> new ConcurrentHashMap<>()); TbAlarmDataSubCtx ctx = new TbAlarmDataSubCtx(serviceId, wsService, entityService, localSubscriptionService, attributesService, stats, alarmService, sessionRef, cmd.getCmdId(), maxEntitiesPerAlarmSubscription, maxAlarmQueriesPerRefreshInterval); @@ -528,7 +528,7 @@ public class DefaultTbEntityDataSubscriptionService implements TbEntityDataSubsc } private TbAlarmCountSubCtx createSubCtx(WebSocketSessionRef sessionRef, AlarmCountCmd cmd) { - Map<Integer, TbAbstractSubCtx> sessionSubs = subscriptionsBySessionId.computeIfAbsent(sessionRef.getSessionId(), k -> new HashMap<>()); + Map<Integer, TbAbstractSubCtx> sessionSubs = subscriptionsBySessionId.computeIfAbsent(sessionRef.getSessionId(), k -> new ConcurrentHashMap<>()); TbAlarmCountSubCtx ctx = new TbAlarmCountSubCtx(serviceId, wsService, entityService, localSubscriptionService, attributesService, stats, alarmService, sessionRef, cmd.getCmdId()); if (cmd.getQuery() != null) { diff --git a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java index 9e08e0359b..2ce913b568 100644 --- a/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/subscription/DefaultTbLocalSubscriptionService.java @@ -83,7 +83,7 @@ import java.util.stream.Collectors; @Service public class DefaultTbLocalSubscriptionService implements TbLocalSubscriptionService { - private final ConcurrentMap<String, Map<Integer, TbSubscription<?>>> subscriptionsBySessionId = new ConcurrentHashMap<>(); + private final ConcurrentMap<String, ConcurrentMap<Integer, TbSubscription<?>>> subscriptionsBySessionId = new ConcurrentHashMap<>(); private final ConcurrentMap<UUID, TbEntityLocalSubsInfo> subscriptionsByEntityId = new ConcurrentHashMap<>(); private final ConcurrentMap<UUID, TbEntityUpdatesInfo> entityUpdates = new ConcurrentHashMap<>(); From 562d6f4d05d8d5d17e8bfb3bc7f78ce835c840f8 Mon Sep 17 00:00:00 2001 From: dashevchenko <dshevchenko@thingsboard.io> Date: Wed, 11 Sep 2024 12:58:30 +0300 Subject: [PATCH 69/80] added platform type to system info --- .../org/thingsboard/server/controller/SystemInfoController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java index bc12171306..9600ac0221 100644 --- a/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java +++ b/application/src/main/java/org/thingsboard/server/controller/SystemInfoController.java @@ -164,6 +164,7 @@ public class SystemInfoController extends BaseController { } else { infoObject.put("version", "unknown"); } + infoObject.put("type", "CE"); return infoObject; } } From c4aff620e36fdd83c2799cfdc9bddb71914a42dc Mon Sep 17 00:00:00 2001 From: Igor Kulikov <ikulikov@thingsboard.io> Date: Wed, 11 Sep 2024 13:39:06 +0300 Subject: [PATCH 70/80] UI: Improve custom components compilation -> use standalone components. --- .../dynamic-component-factory.service.ts | 93 ++++--------------- .../app/core/services/resources.service.ts | 71 +------------- .../custom-dialog-container.component.ts | 13 ++- .../widget/dialog/custom-dialog.service.ts | 7 +- .../widget/widget-component.service.ts | 5 +- .../components/widget/widget.component.ts | 2 +- .../home/models/widget-component.models.ts | 4 +- .../shared/components/markdown.component.ts | 12 ++- 8 files changed, 42 insertions(+), 165 deletions(-) diff --git a/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts b/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts index d18797a1be..1c7150bac3 100644 --- a/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts +++ b/ui-ngx/src/app/core/services/dynamic-component-factory.service.ts @@ -14,49 +14,17 @@ /// limitations under the License. /// -import { - Compiler, - Component, - Injectable, - Injector, - NgModule, - NgModuleRef, - OnDestroy, - Type, ɵNG_COMP_DEF, - ɵresetCompiledComponents -} from '@angular/core'; +import { Component, Injectable, Type, ɵComponentDef, ɵNG_COMP_DEF } from '@angular/core'; import { from, Observable, of } from 'rxjs'; import { CommonModule } from '@angular/common'; import { mergeMap } from 'rxjs/operators'; -@NgModule() -export abstract class DynamicComponentModule implements OnDestroy { - - // eslint-disable-next-line @angular-eslint/contextual-lifecycle - ngOnDestroy(): void { - } - -} - -interface DynamicComponentData<T> { - componentType: Type<T>; - componentModuleRef: NgModuleRef<DynamicComponentModule>; -} - -interface DynamicComponentModuleData { - moduleRef: NgModuleRef<DynamicComponentModule>; - moduleType: Type<DynamicComponentModule>; -} - @Injectable({ providedIn: 'root' }) export class DynamicComponentFactoryService { - private dynamicComponentModulesMap = new Map<Type<any>, DynamicComponentModuleData>(); - - constructor(private compiler: Compiler, - private injector: Injector) { + constructor() { } public createDynamicComponent<T>( @@ -64,59 +32,38 @@ export class DynamicComponentFactoryService { template: string, modules?: Type<any>[], preserveWhitespaces?: boolean, - styles?: string[]): Observable<DynamicComponentData<T>> { + styles?: string[]): Observable<Type<T>> { return from(import('@angular/compiler')).pipe( mergeMap(() => { - const comp = this._createDynamicComponent(componentType, template, preserveWhitespaces, styles); - let moduleImports: Type<any>[] = [CommonModule]; + let componentImports: Type<any>[] = [CommonModule]; if (modules) { - moduleImports = [...moduleImports, ...modules]; + componentImports = [...componentImports, ...modules]; } - // noinspection AngularInvalidImportedOrDeclaredSymbol - const dynamicComponentInstanceModule = NgModule({ - declarations: [comp], - imports: moduleImports - })(class DynamicComponentInstanceModule extends DynamicComponentModule {}); - - const module = this.compiler.compileModuleSync(dynamicComponentInstanceModule); - let moduleRef: NgModuleRef<any>; - try { - moduleRef = module.create(this.injector); - // eslint-disable-next-line - comp[ɵNG_COMP_DEF]; - } catch (e) { - this.compiler.clearCacheFor(module.moduleType); - ɵresetCompiledComponents(); - throw e; - } - this.dynamicComponentModulesMap.set(comp, { - moduleRef, - moduleType: module.moduleType - }); - return of( { - componentType: comp, - componentModuleRef: moduleRef - }); + const comp = this.createAndCompileDynamicComponent(componentType, template, componentImports, preserveWhitespaces, styles); + return of(comp.type); }) ); } - public destroyDynamicComponent<T>(componentType: Type<T>) { - const moduleData = this.dynamicComponentModulesMap.get(componentType); - if (moduleData) { - moduleData.moduleRef.destroy(); - this.compiler.clearCacheFor(moduleData.moduleType); - this.dynamicComponentModulesMap.delete(componentType); - } + public destroyDynamicComponent<T>(_componentType: Type<T>) { + } + + public getComponentDef<T>(componentType: Type<T>): ɵComponentDef<T> { + return componentType[ɵNG_COMP_DEF]; } - private _createDynamicComponent<T>(componentType: Type<T>, template: string, preserveWhitespaces?: boolean, styles?: string[]): Type<T> { + private createAndCompileDynamicComponent<T>(componentType: Type<T>, template: string, imports: Type<any>[], + preserveWhitespaces?: boolean, styles?: string[]): ɵComponentDef<T> { // noinspection AngularMissingOrInvalidDeclarationInModule - return Component({ + const comp = Component({ template, + imports, preserveWhitespaces, - styles + styles, + standalone: true })(componentType); + // Trigger component compilation + return comp[ɵNG_COMP_DEF]; } } diff --git a/ui-ngx/src/app/core/services/resources.service.ts b/ui-ngx/src/app/core/services/resources.service.ts index 449e950a65..013c3e5d72 100644 --- a/ui-ngx/src/app/core/services/resources.service.ts +++ b/ui-ngx/src/app/core/services/resources.service.ts @@ -21,7 +21,7 @@ import { Injectable, Injector, ModuleWithComponentFactories, - Type + Type, ɵNG_MOD_DEF } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { forkJoin, Observable, ReplaySubject, throwError } from 'rxjs'; @@ -50,7 +50,6 @@ export class ResourcesService { private loadedJsonResources: { [url: string]: ReplaySubject<any> } = {}; private loadedResources: { [url: string]: ReplaySubject<void> } = {}; - private loadedModules: { [url: string]: ReplaySubject<Type<any>[]> } = {}; private loadedModulesAndFactories: { [url: string]: ReplaySubject<ModulesWithFactories> } = {}; private anchor = this.document.getElementsByTagName('head')[0] || this.document.getElementsByTagName('body')[0]; @@ -201,71 +200,6 @@ export class ResourcesService { ); } - public loadModules(resourceId: string | TbResourceId, modulesMap: IModulesMap): Observable<Type<any>[]> { - const url = this.getDownloadUrl(resourceId); - if (this.loadedModules[url]) { - return this.loadedModules[url].asObservable(); - } - modulesMap.init(); - const meta = this.getMetaInfo(resourceId); - const subject = new ReplaySubject<Type<any>[]>(); - this.loadedModules[url] = subject; - import('@angular/compiler').then( - () => { - System.import(url, undefined, meta).then( - (module) => { - try { - let modules; - try { - modules = this.extractNgModules(module); - } catch (e) { - console.error(e); - } - if (modules && modules.length) { - const tasks: Promise<ModuleWithComponentFactories<any>>[] = []; - for (const m of modules) { - tasks.push(this.compiler.compileModuleAndAllComponentsAsync(m)); - } - forkJoin(tasks).subscribe((compiled) => { - try { - for (const c of compiled) { - c.ngModuleFactory.create(this.injector); - } - this.loadedModules[url].next(modules); - this.loadedModules[url].complete(); - } catch (e) { - this.loadedModules[url].error(new Error(`Unable to init module from url: ${url}`)); - } - }, - (e) => { - this.loadedModules[url].error(new Error(`Unable to compile module from url: ${url}`)); - }); - } else { - this.loadedModules[url].error(new Error(`Module '${url}' doesn't have default export or not NgModule!`)); - } - } catch (e) { - this.loadedModules[url].error(new Error(`Unable to load module from url: ${url}`)); - } - }, - (e) => { - this.loadedModules[url].error(new Error(`Unable to load module from url: ${url}`)); - console.error(`Unable to load module from url: ${url}`, e); - } - ); - } - ); - return subject.asObservable().pipe( - tap({ - next: () => System.delete(url), - error: () => { - delete this.loadedModulesAndFactories[url]; - System.delete(url); - }, - complete: () => System.delete(url) - }) - ); - } - private extractNgModules(module: any, modules: Type<any>[] = []): Type<any>[] { try { let potentialModules = [module]; @@ -274,7 +208,7 @@ export class ResourcesService { while (potentialModules.length && currentScanDepth < 10) { const newPotentialModules = []; for (const potentialModule of potentialModules) { - if (potentialModule && ('ɵmod' in potentialModule)) { + if (potentialModule && (ɵNG_MOD_DEF in potentialModule)) { modules.push(potentialModule); } else { for (const k of Object.keys(potentialModule)) { @@ -349,7 +283,6 @@ export class ResourcesService { } private clearModulesCache() { - this.loadedModules = {}; this.loadedModulesAndFactories = {}; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts b/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts index 089297427f..889a19a5aa 100644 --- a/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog-container.component.ts @@ -17,11 +17,12 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Component, - ComponentFactory, - ComponentRef, HostBinding, + ComponentRef, + HostBinding, Inject, - Injector, NgModuleRef, - OnDestroy, Type, + Injector, + OnDestroy, + Type, ViewContainerRef } from '@angular/core'; import { DialogComponent } from '@shared/components/dialog.component'; @@ -35,13 +36,11 @@ import { } from '@home/components/widget/dialog/custom-dialog.component'; import { DialogService } from '@core/services/dialog.service'; import { TranslateService } from '@ngx-translate/core'; -import { DynamicComponentModule } from '@core/services/dynamic-component-factory.service'; export interface CustomDialogContainerData { controller: (instance: CustomDialogComponent) => void; data?: any; customComponentType: Type<CustomDialogComponent>; - customComponentModuleRef: NgModuleRef<DynamicComponentModule>; } @Component({ @@ -80,7 +79,7 @@ export class CustomDialogContainerComponent extends DialogComponent<CustomDialog }); try { this.customComponentRef = this.viewContainerRef.createComponent(this.data.customComponentType, - {index: 0, injector, ngModuleRef: this.data.customComponentModuleRef}); + {index: 0, injector}); } catch (e: any) { let message; if (e.message?.startsWith('NG0')) { diff --git a/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.service.ts b/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.service.ts index ba3b080936..2705a8902c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/dialog/custom-dialog.service.ts @@ -60,11 +60,10 @@ export class CustomDialogService { } return this.dynamicComponentFactoryService.createDynamicComponent( class CustomDialogComponentInstance extends CustomDialogComponent {}, template, modules).pipe( - mergeMap((componentData) => { + mergeMap((componentType) => { const dialogData: CustomDialogContainerData = { controller, - customComponentType: componentData.componentType, - customComponentModuleRef: componentData.componentModuleRef, + customComponentType: componentType, data }; let dialogConfig: MatDialogConfig = { @@ -79,7 +78,7 @@ export class CustomDialogService { CustomDialogContainerComponent, dialogConfig).afterClosed().pipe( tap(() => { - this.dynamicComponentFactoryService.destroyDynamicComponent(componentData.componentType); + this.dynamicComponentFactoryService.destroyDynamicComponent(componentType); }) ); } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts index 508d07ea0d..8e1e6f1b3a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts @@ -381,9 +381,8 @@ export class WidgetComponentService { widgetInfo.templateHtml, resolvedModules.modules ).pipe( - map((componentData) => { - widgetInfo.componentType = componentData.componentType; - widgetInfo.componentModuleRef = componentData.componentModuleRef; + map((componentType) => { + widgetInfo.componentType = componentType; return null; }), catchError(e => { diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts index 76845a11ef..5bd4910af7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts @@ -760,7 +760,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI try { this.dynamicWidgetComponentRef = this.widgetContentContainer.createComponent(this.widgetInfo.componentType, - {index: 0, injector, ngModuleRef: this.widgetInfo.componentModuleRef}); + {index: 0, injector}); this.cd.detectChanges(); } catch (e) { if (this.dynamicWidgetComponentRef) { diff --git a/ui-ngx/src/app/modules/home/models/widget-component.models.ts b/ui-ngx/src/app/modules/home/models/widget-component.models.ts index 5a1a28472e..673bc21edb 100644 --- a/ui-ngx/src/app/modules/home/models/widget-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/widget-component.models.ts @@ -47,7 +47,7 @@ import { WidgetActionsApi, WidgetSubscriptionApi } from '@core/api/widget-api.models'; -import { ChangeDetectorRef, Injector, NgModuleRef, NgZone, Type } from '@angular/core'; +import { ChangeDetectorRef, Injector, NgZone, Type } from '@angular/core'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { RafService } from '@core/services/raf.service'; import { WidgetTypeId } from '@shared/models/id/widget-type-id'; @@ -101,7 +101,6 @@ import { AlarmQuery, AlarmSearchStatus, AlarmStatus } from '@app/shared/models/a import { ImagePipe, MillisecondsToTimeStringPipe, TelemetrySubscriber } from '@app/shared/public-api'; import { UserId } from '@shared/models/id/user-id'; import { UserSettingsService } from '@core/http/user-settings.service'; -import { DynamicComponentModule } from '@core/services/dynamic-component-factory.service'; import { DataKeySettingsFunction } from '@home/components/widget/config/data-keys.component.models'; import { UtilsService } from '@core/services/utils.service'; @@ -549,7 +548,6 @@ export interface WidgetInfo extends WidgetTypeDescriptor, WidgetControllerDescri description?: string; tags?: string[]; componentType?: Type<IDynamicWidgetComponent>; - componentModuleRef?: NgModuleRef<DynamicComponentModule>; } export interface WidgetConfigComponentData { diff --git a/ui-ngx/src/app/shared/components/markdown.component.ts b/ui-ngx/src/app/shared/components/markdown.component.ts index 069bca2b2d..d890817d04 100644 --- a/ui-ngx/src/app/shared/components/markdown.component.ts +++ b/ui-ngx/src/app/shared/components/markdown.component.ts @@ -22,7 +22,8 @@ import { EventEmitter, Inject, Injector, - Input, NgZone, + Input, + NgZone, OnChanges, Output, Renderer2, @@ -132,7 +133,8 @@ export class TbMarkdownComponent implements OnChanges { let readyObservable: Observable<void>; if (this.applyDefaultMarkdownStyle) { if (!defaultMarkdownStyle) { - defaultMarkdownStyle = deepClone(TbMarkdownComponent['ɵcmp'].styles)[0].replace(/\[_nghost\-%COMP%\]/g, '') + const compDef = this.dynamicComponentFactoryService.getComponentDef(TbMarkdownComponent); + defaultMarkdownStyle = deepClone(compDef.styles[0]).replace(/\[_nghost\-%COMP%\]/g, '') .replace(/\[_ngcontent\-%COMP%\]/g, ''); } styles.push(defaultMarkdownStyle); @@ -161,13 +163,13 @@ export class TbMarkdownComponent implements OnChanges { template, compileModules, true, styles - ).subscribe((componentData) => { - this.tbMarkdownInstanceComponentType = componentData.componentType; + ).subscribe((componentType) => { + this.tbMarkdownInstanceComponentType = componentType; const injector: Injector = Injector.create({providers: [], parent: this.markdownContainer.injector}); try { this.tbMarkdownInstanceComponentRef = this.markdownContainer.createComponent(this.tbMarkdownInstanceComponentType, - {index: 0, injector, ngModuleRef: componentData.componentModuleRef}); + {index: 0, injector}); if (this.context) { for (const propName of Object.keys(this.context)) { this.tbMarkdownInstanceComponentRef.instance[propName] = this.context[propName]; From d435f91fac0c33f185ba015276e44341b1937069 Mon Sep 17 00:00:00 2001 From: mpetrov <mpetrov@thingsboard.io> Date: Wed, 11 Sep 2024 16:34:30 +0300 Subject: [PATCH 71/80] Made Resource details page read only for LwM2M resources --- .../resource/resources-library.component.html | 2 +- .../resource/resources-library.component.ts | 39 ++++++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library.component.html b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library.component.html index 5c3d9da081..441a311021 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library.component.html +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library.component.html @@ -58,7 +58,7 @@ </mat-form-field> <mat-form-field class="mat-block" *ngIf="entityForm.get('resourceType').value !== resourceType.LWM2M_MODEL || !isAdd"> <mat-label translate>resource.title</mat-label> - <input matInput formControlName="title" required [readonly]="entityForm.get('resourceType').value === resourceType.LWM2M_MODEL"> + <input matInput formControlName="title" required> <mat-error *ngIf="entityForm.get('title').hasError('required')"> {{ 'resource.title-required' | translate }} </mat-error> diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library.component.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library.component.ts index f6a8befe9b..de61618dd7 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library.component.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library.component.ts @@ -43,8 +43,7 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme readonly resourceType = ResourceType; readonly resourceTypes: ResourceType[] = Object.values(this.resourceType); readonly resourceTypesTranslationMap = ResourceTypeTranslationMap; - - maxResourceSize = getCurrentAuthState(this.store).maxResourceSize; + readonly maxResourceSize = getCurrentAuthState(this.store).maxResourceSize; private destroy$ = new Subject<void>(); @@ -57,20 +56,20 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme super(store, fb, entityValue, entitiesTableConfigValue, cd); } - ngOnInit() { + ngOnInit(): void { super.ngOnInit(); if (this.isAdd) { this.observeResourceTypeChange(); } } - ngOnDestroy() { + ngOnDestroy(): void { super.ngOnDestroy(); this.destroy$.next(); this.destroy$.complete(); } - hideDelete() { + hideDelete(): boolean { if (this.entitiesTableConfig) { return !this.entitiesTableConfig.deleteEnabled(this.entity); } else { @@ -87,19 +86,18 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme }); } - updateForm(entity: Resource) { + updateForm(entity: Resource): void { + const { resourceType, fileName, title, data } = entity; + this.updateTableReadonlyConfig(); + if (this.isEdit) { - this.entityForm.get('resourceType').disable({emitEvent: false}); - if (entity.resourceType !== ResourceType.JS_MODULE) { - this.entityForm.get('fileName').disable({emitEvent: false}); + this.entityForm.get('resourceType').disable({ emitEvent: false }); + if (resourceType !== ResourceType.JS_MODULE) { + this.entityForm.get('fileName').disable({ emitEvent: false }); } } - this.entityForm.patchValue({ - resourceType: entity.resourceType, - fileName: entity.fileName, - title: entity.title, - data: entity.data - }); + + this.entityForm.patchValue({ resourceType, fileName, title, data }); } prepareFormValue(formValue: Resource): Resource { @@ -109,7 +107,7 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme return super.prepareFormValue(formValue); } - getAllowedExtensions() { + getAllowedExtensions(): string { try { return ResourceTypeExtension.get(this.entityForm.get('resourceType').value); } catch (e) { @@ -117,7 +115,7 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme } } - getAcceptType() { + getAcceptType(): string { try { return ResourceTypeMIMETypes.get(this.entityForm.get('resourceType').value); } catch (e) { @@ -129,7 +127,7 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme return window.btoa(data); } - onResourceIdCopied() { + onResourceIdCopied(): void { this.store.dispatch(new ActionNotificationShow( { message: this.translate.instant('resource.idCopiedMessage'), @@ -140,6 +138,11 @@ export class ResourcesLibraryComponent extends EntityComponent<Resource> impleme })); } + private updateTableReadonlyConfig(): void { + this.entitiesTableConfigValue.detailsReadonly = () => + this.resourceType.LWM2M_MODEL === this.entityForm.get('resourceType').value; + } + private observeResourceTypeChange(): void { this.entityForm.get('resourceType').valueChanges.pipe( startWith(ResourceType.JS_MODULE), From 148108006c29fa5537efca6cd02b1830987244e3 Mon Sep 17 00:00:00 2001 From: mpetrov <mpetrov@thingsboard.io> Date: Wed, 11 Sep 2024 17:15:20 +0300 Subject: [PATCH 72/80] [4114] fixed number version bug, added hide new field for opc and refactoring --- ...teway-connector-version-processor.abstract.ts | 16 ++++++++++------ .../modbus-version-processor.abstract.ts | 8 ++++---- .../abstract/mqtt-version-processor.abstract.ts | 8 ++++---- .../abstract/opc-version-processor.abstract.ts | 8 ++++---- .../opc-server-config.component.html | 2 +- .../opc-server-config.component.ts | 15 +++++++++++++-- .../opc-ua-basic-config.component.html | 2 +- .../opc-ua-basic-config.component.ts | 1 + .../opc-ua-legacy-basic-config.component.ts | 1 + .../widget/lib/gateway/gateway-widget.models.ts | 8 ++++---- .../connector-default-configs/modbus.json | 2 +- .../metadata/connector-default-configs/mqtt.json | 2 +- .../connector-default-configs/opcua.json | 2 +- 13 files changed, 46 insertions(+), 29 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts index 5f06659823..944b5ffe6c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract.ts @@ -15,14 +15,14 @@ /// import { GatewayConnector, GatewayVersion } from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { isString } from '@core/utils'; +import { isNumber, isString } from '@core/utils'; export abstract class GatewayConnectorVersionProcessor<BasicConfig> { gatewayVersion: number; configVersion: number; - protected constructor(protected gatewayVersionStr: string, protected connector: GatewayConnector<BasicConfig>) { - this.gatewayVersion = this.parseVersion(this.gatewayVersionStr); + protected constructor(protected gatewayVersionIn: string | number, protected connector: GatewayConnector<BasicConfig>) { + this.gatewayVersion = this.parseVersion(this.gatewayVersionIn); this.configVersion = this.parseVersion(connector.configVersion); } @@ -45,11 +45,15 @@ export abstract class GatewayConnectorVersionProcessor<BasicConfig> { } private isVersionUpgradeNeeded(): boolean { - return this.gatewayVersionStr === GatewayVersion.Current && (!this.configVersion || this.configVersion < this.gatewayVersion); + return this.gatewayVersionIn === GatewayVersion.Current && (!this.configVersion || this.configVersion < this.gatewayVersion); } - private parseVersion(version: string): number { - return isString(version) ? Number(version.replace(/\./g, '')) : 0; + private parseVersion(version: string | number): number { + if (isNumber(version)) { + return version as number; + } + + return isString(version) ? parseFloat((version as string).replace(/\./g, '').slice(0, 3)) / 100 : 0; } protected abstract getDowngradedVersion(): GatewayConnector<BasicConfig>; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts index abcf6ce597..6ea8f4516d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract.ts @@ -29,10 +29,10 @@ import { ModbusVersionMappingUtil } from '@home/components/widget/lib/gateway/ut export class ModbusVersionProcessor extends GatewayConnectorVersionProcessor<any> { constructor( - protected gatewayVersionStr: string, + protected gatewayVersionIn: string, protected connector: GatewayConnector<ModbusBasicConfig> ) { - super(gatewayVersionStr, connector); + super(gatewayVersionIn, connector); } getUpgradedVersion(): GatewayConnector<ModbusBasicConfig_v3_5_2> { @@ -47,7 +47,7 @@ export class ModbusVersionProcessor extends GatewayConnectorVersionProcessor<any ? ModbusVersionMappingUtil.mapSlaveToUpgradedVersion(configurationJson.slave as ModbusLegacySlave) : {} as ModbusSlave, }, - configVersion: this.gatewayVersionStr + configVersion: this.gatewayVersionIn } as GatewayConnector<ModbusBasicConfig_v3_5_2>; } @@ -62,7 +62,7 @@ export class ModbusVersionProcessor extends GatewayConnectorVersionProcessor<any : {} as ModbusLegacySlave, master: configurationJson.master, }, - configVersion: this.gatewayVersionStr + configVersion: this.gatewayVersionIn } as GatewayConnector<ModbusLegacyBasicConfig>; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts index f55269eadf..351ad76494 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract.ts @@ -31,10 +31,10 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor<MQTTB private readonly mqttRequestTypeKeys = Object.values(RequestType); constructor( - protected gatewayVersionStr: string, + protected gatewayVersionIn: string, protected connector: GatewayConnector<MQTTBasicConfig> ) { - super(gatewayVersionStr, connector); + super(gatewayVersionIn, connector); } getUpgradedVersion(): GatewayConnector<MQTTBasicConfig_v3_5_2> { @@ -67,7 +67,7 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor<MQTTB return { ...this.connector, configurationJson, - configVersion: this.gatewayVersionStr + configVersion: this.gatewayVersionIn } as GatewayConnector<MQTTBasicConfig_v3_5_2>; } @@ -85,7 +85,7 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor<MQTTB ...updatedRequestsMapping, mapping: updatedMapping, }, - configVersion: this.gatewayVersionStr + configVersion: this.gatewayVersionIn } as GatewayConnector<MQTTLegacyBasicConfig>; } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts index e0337d9fe3..e89c48fc28 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/abstract/opc-version-processor.abstract.ts @@ -26,10 +26,10 @@ import { OpcVersionMappingUtil } from '@home/components/widget/lib/gateway/utils export class OpcVersionProcessor extends GatewayConnectorVersionProcessor<OPCBasicConfig> { constructor( - protected gatewayVersionStr: string, + protected gatewayVersionIn: string, protected connector: GatewayConnector<OPCBasicConfig> ) { - super(gatewayVersionStr, connector); + super(gatewayVersionIn, connector); } getUpgradedVersion(): GatewayConnector<OPCBasicConfig_v3_5_2> { @@ -40,7 +40,7 @@ export class OpcVersionProcessor extends GatewayConnectorVersionProcessor<OPCBas server: server ? OpcVersionMappingUtil.mapServerToUpgradedVersion(server) : {}, mapping: server.mapping ? OpcVersionMappingUtil.mapMappingToUpgradedVersion(server.mapping) : [], }, - configVersion: this.gatewayVersionStr + configVersion: this.gatewayVersionIn } as GatewayConnector<OPCBasicConfig_v3_5_2>; } @@ -50,7 +50,7 @@ export class OpcVersionProcessor extends GatewayConnectorVersionProcessor<OPCBas configurationJson: { server: OpcVersionMappingUtil.mapServerToDowngradedVersion(this.connector.configurationJson as OPCBasicConfig_v3_5_2) }, - configVersion: this.gatewayVersionStr + configVersion: this.gatewayVersionIn } as GatewayConnector<OPCLegacyBasicConfig>; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.html index 584679fa2c..523705d029 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.html @@ -84,7 +84,7 @@ </mat-form-field> </div> </div> - <div class="tb-form-row column-xs" fxLayoutAlign="space-between center"> + <div *ngIf="!hideNewFields" class="tb-form-row column-xs" fxLayoutAlign="space-between center"> <div class="fixed-title-width" tb-hint-tooltip-icon="{{ 'gateway.hints.poll-period' | translate }}"> <div tbTruncateWithTooltip>{{ 'gateway.poll-period' | translate }}</div> </div> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.ts index c838121b76..c000139ded 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-server-config/opc-server-config.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { ChangeDetectionStrategy, Component, forwardRef, OnDestroy } from '@angular/core'; +import { AfterViewInit, ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy } from '@angular/core'; import { ControlValueAccessor, FormBuilder, @@ -39,6 +39,7 @@ import { SecurityConfigComponent } from '@home/components/widget/lib/gateway/connectors-configuration/security-config/security-config.component'; import { HOUR } from '@shared/models/time/time.models'; +import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ selector: 'tb-opc-server-config', @@ -64,7 +65,11 @@ import { HOUR } from '@shared/models/time/time.models'; SecurityConfigComponent, ] }) -export class OpcServerConfigComponent implements ControlValueAccessor, Validator, OnDestroy { +export class OpcServerConfigComponent implements ControlValueAccessor, Validator, AfterViewInit, OnDestroy { + + @Input() + @coerceBoolean() + hideNewFields: boolean = false; securityPolicyTypes = SecurityPolicyTypes; serverConfigFormGroup: UntypedFormGroup; @@ -95,6 +100,12 @@ export class OpcServerConfigComponent implements ControlValueAccessor, Validator }); } + ngAfterViewInit(): void { + if (this.hideNewFields) { + this.serverConfigFormGroup.get('pollPeriodInMillis').disable({emitEvent: false}); + } + } + ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.html index 5f8b25af9d..2296a472a4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.html @@ -20,7 +20,7 @@ <ng-container [ngTemplateOutlet]="generalTabContent"></ng-container> </mat-tab> <mat-tab label="{{ 'gateway.server' | translate }}*"> - <tb-opc-server-config formControlName="server"></tb-opc-server-config> + <tb-opc-server-config formControlName="server" [hideNewFields]="isLegacy"></tb-opc-server-config> </mat-tab> <mat-tab label="{{ 'gateway.data-mapping' | translate }}*"> <div class="tb-form-panel no-border no-padding padding-top tb-flex fill-height"> diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.ts index 1a45e74c7a..c45eafcc67 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-basic-config.component.ts @@ -63,6 +63,7 @@ import { export class OpcUaBasicConfigComponent extends GatewayConnectorBasicConfigDirective<OPCBasicConfig_v3_5_2, OPCBasicConfig_v3_5_2> { mappingTypes = MappingType; + isLegacy = false; protected override initBasicFormGroup(): FormGroup { return this.fb.group({ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-legacy-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-legacy-basic-config.component.ts index 12e05205a2..9458858cbf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-legacy-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc/opc-ua-basic-config/opc-ua-legacy-basic-config.component.ts @@ -64,6 +64,7 @@ import { OpcVersionMappingUtil } from '@home/components/widget/lib/gateway/utils export class OpcUaLegacyBasicConfigComponent extends GatewayConnectorBasicConfigDirective<OPCBasicConfig_v3_5_2, OPCLegacyBasicConfig> { mappingTypes = MappingType; + isLegacy = true; protected override initBasicFormGroup(): FormGroup { return this.fb.group({ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index b933ff1186..0f940e28ff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -131,7 +131,7 @@ export interface GatewayConnector<BaseConfig = ConnectorBaseConfig> extends Gate export interface GatewayVersionedDefaultConfig { legacy: GatewayConnector<ConnectorLegacyConfig>; - '3.5.1': GatewayConnector<ConnectorBaseConfig_v_3_5_2>; + '3.5.2': GatewayConnector<ConnectorBaseConfig_v3_5_2>; } export interface DataMapping { @@ -189,7 +189,7 @@ export interface ConnectorSecurity { } export enum GatewayVersion { - Current = '3.5.1', + Current = '3.5.2', Legacy = 'legacy' } @@ -197,11 +197,11 @@ export type ConnectorMapping = DeviceConnectorMapping | RequestMappingValue | Co export type ConnectorMappingFormValue = DeviceConnectorMapping | RequestMappingFormValue | ConverterMappingFormValue; -export type ConnectorBaseConfig = ConnectorBaseConfig_v_3_5_2 | ConnectorLegacyConfig; +export type ConnectorBaseConfig = ConnectorBaseConfig_v3_5_2 | ConnectorLegacyConfig; export type ConnectorLegacyConfig = ConnectorBaseInfo | MQTTLegacyBasicConfig | OPCLegacyBasicConfig | ModbusBasicConfig; -export type ConnectorBaseConfig_v_3_5_2 = ConnectorBaseInfo | MQTTBasicConfig_v3_5_2 | OPCBasicConfig_v3_5_2; +export type ConnectorBaseConfig_v3_5_2 = ConnectorBaseInfo | MQTTBasicConfig_v3_5_2 | OPCBasicConfig_v3_5_2; export interface ConnectorBaseInfo { name: string; diff --git a/ui-ngx/src/assets/metadata/connector-default-configs/modbus.json b/ui-ngx/src/assets/metadata/connector-default-configs/modbus.json index 96fb59dcf5..38bb44e036 100644 --- a/ui-ngx/src/assets/metadata/connector-default-configs/modbus.json +++ b/ui-ngx/src/assets/metadata/connector-default-configs/modbus.json @@ -1,5 +1,5 @@ { - "3.5.1": { + "3.5.2": { "master": { "slaves": [ { diff --git a/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json b/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json index b3ba47215f..5b8b8dbd44 100644 --- a/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json +++ b/ui-ngx/src/assets/metadata/connector-default-configs/mqtt.json @@ -1,5 +1,5 @@ { - "3.5.1": { + "3.5.2": { "broker": { "host": "127.0.0.1", "port": 1883, diff --git a/ui-ngx/src/assets/metadata/connector-default-configs/opcua.json b/ui-ngx/src/assets/metadata/connector-default-configs/opcua.json index eb33f9235e..c0ef993dd1 100644 --- a/ui-ngx/src/assets/metadata/connector-default-configs/opcua.json +++ b/ui-ngx/src/assets/metadata/connector-default-configs/opcua.json @@ -1,5 +1,5 @@ { - "3.5.1": { + "3.5.2": { "server": { "url": "localhost:4840/freeopcua/server/", "timeoutInMillis": 5000, From 70de7f441226f7fc669e8ff0878283fe2d132d6f Mon Sep 17 00:00:00 2001 From: Igor Kulikov <ikulikov@thingsboard.io> Date: Wed, 11 Sep 2024 17:30:13 +0300 Subject: [PATCH 73/80] UI: Introduce new SCADA symbol property type 'icon'. --- .../left-analog-water-level-meter.svg | 58 +++++++++++++-- .../right-analog-water-level-meter.svg | 60 ++++++++++++++-- .../scada/scada-symbol-widget.component.ts | 5 +- .../widget/lib/scada/scada-symbol.models.ts | 72 +++++++++++++++++-- ...cada-symbol-object-settings.component.html | 4 ++ ...scada-symbol-property-panel.component.html | 4 ++ .../scada-symbol-property-row.component.ts | 2 + .../scada-symbol-editor.models.ts | 48 ++++++++++--- .../assets/locale/locale.constant-en_US.json | 1 + 9 files changed, 229 insertions(+), 25 deletions(-) diff --git a/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg b/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg index e242edfc11..c2b2a32a2d 100644 --- a/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/left-analog-water-level-meter.svg @@ -37,12 +37,12 @@ }, { "tag": "icon", - "stateRenderFunction": "var icon = ctx.properties.icon;\nif (icon) {\n element.show();\n} else {\n element.hide()\n}", + "stateRenderFunction": "var showIcon = ctx.properties.showIcon;\nif (showIcon) {\n element.show();\n var icon = ctx.properties.icon;\n var iconSize = ctx.properties.iconSize;\n var iconColor = ctx.properties.iconColor;\n ctx.api.icon(element, icon, iconSize, iconColor, true);\n} else {\n element.hide()\n}", "actions": null }, { "tag": "label", - "stateRenderFunction": "var label = ctx.properties.label;\nif (label) {\n var icon = ctx.properties.icon;\n var labelTextFont = ctx.properties.labelTextFont;\n var labelTextColor = ctx.properties.labelTextColor;\n ctx.api.font(element, labelTextFont, labelTextColor);\n ctx.api.text(element, ctx.properties.labelText);\n if (!icon) {\n element.transform({translateX: 10});\n }\n element.show();\n} else {\n element.hide();\n}", + "stateRenderFunction": "var label = ctx.properties.label;\nif (label) {\n var showIcon = ctx.properties.showIcon;\n var labelTextFont = ctx.properties.labelTextFont;\n var labelTextColor = ctx.properties.labelTextColor;\n ctx.api.font(element, labelTextFont, labelTextColor);\n ctx.api.text(element, ctx.properties.labelText);\n if (!showIcon) {\n element.transform({translateX: 10});\n }\n element.show();\n} else {\n element.hide();\n}", "actions": null }, { @@ -357,7 +357,7 @@ "step": null }, { - "id": "icon", + "id": "showIcon", "name": "{i18n:scada.symbol.icon}", "type": "switch", "default": true, @@ -372,6 +372,54 @@ "max": null, "step": null }, + { + "id": "iconSize", + "name": "{i18n:scada.symbol.icon}", + "type": "number", + "default": 14, + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": "px", + "disableOnProperty": "showIcon", + "rowClass": "", + "fieldClass": "", + "min": 0, + "max": null, + "step": null + }, + { + "id": "icon", + "name": "{i18n:scada.symbol.icon}", + "type": "icon", + "default": "water", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "showIcon", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "iconColor", + "name": "{i18n:scada.symbol.icon}", + "type": "color", + "default": "#0000008A", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "showIcon", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, { "id": "defaultBorderColor", "name": "{i18n:scada.symbol.default-border-color}", @@ -616,7 +664,9 @@ } - Water + Water + + diff --git a/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg b/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg index e75949e374..739505d421 100644 --- a/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg +++ b/application/src/main/data/json/system/scada_symbols/right-analog-water-level-meter.svg @@ -1,5 +1,5 @@ { - "title": "Rigth analog water level meter", + "title": "Right analog water level meter", "description": "Right analog water level meter", "searchTags": [ "water meter" @@ -37,12 +37,12 @@ }, { "tag": "icon", - "stateRenderFunction": "var icon = ctx.properties.icon;\nif (icon) {\n element.show();\n} else {\n element.hide()\n}", + "stateRenderFunction": "var showIcon = ctx.properties.showIcon;\nif (showIcon) {\n element.show();\n var icon = ctx.properties.icon;\n var iconSize = ctx.properties.iconSize;\n var iconColor = ctx.properties.iconColor;\n ctx.api.icon(element, icon, iconSize, iconColor, true);\n} else {\n element.hide()\n}", "actions": null }, { "tag": "label", - "stateRenderFunction": "var label = ctx.properties.label;\nif (label) {\n var icon = ctx.properties.icon;\n var labelTextFont = ctx.properties.labelTextFont;\n var labelTextColor = ctx.properties.labelTextColor;\n ctx.api.font(element, labelTextFont, labelTextColor);\n ctx.api.text(element, ctx.properties.labelText);\n if (!icon) {\n element.transform({translateX: 10});\n }\n element.show();\n} else {\n element.hide();\n}", + "stateRenderFunction": "var label = ctx.properties.label;\nif (label) {\n var showIcon = ctx.properties.showIcon;\n var labelTextFont = ctx.properties.labelTextFont;\n var labelTextColor = ctx.properties.labelTextColor;\n ctx.api.font(element, labelTextFont, labelTextColor);\n ctx.api.text(element, ctx.properties.labelText);\n if (!showIcon) {\n element.transform({translateX: 10});\n }\n element.show();\n} else {\n element.hide();\n}", "actions": null }, { @@ -357,7 +357,7 @@ "step": null }, { - "id": "icon", + "id": "showIcon", "name": "{i18n:scada.symbol.icon}", "type": "switch", "default": true, @@ -372,6 +372,54 @@ "max": null, "step": null }, + { + "id": "iconSize", + "name": "{i18n:scada.symbol.icon}", + "type": "number", + "default": 14, + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": "px", + "disableOnProperty": "showIcon", + "rowClass": "", + "fieldClass": "", + "min": 0, + "max": null, + "step": null + }, + { + "id": "icon", + "name": "{i18n:scada.symbol.icon}", + "type": "icon", + "default": "water", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "showIcon", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, + { + "id": "iconColor", + "name": "{i18n:scada.symbol.icon}", + "type": "color", + "default": "#0000008A", + "required": null, + "subLabel": null, + "divider": null, + "fieldSuffix": null, + "disableOnProperty": "showIcon", + "rowClass": "", + "fieldClass": "", + "min": null, + "max": null, + "step": null + }, { "id": "defaultBorderColor", "name": "{i18n:scada.symbol.default-border-color}", @@ -616,7 +664,9 @@ } - Water + Water + + diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol-widget.component.ts index 6db0d202c7..010cb9d6bc 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol-widget.component.ts @@ -40,6 +40,7 @@ import { WidgetComponent } from '@home/components/widget/widget.component'; import { isDefinedAndNotNull, mergeDeep } from '@core/utils'; import { WidgetContext } from '@home/models/widget-component.models'; import { catchError, share } from 'rxjs/operators'; +import { MatIconRegistry } from '@angular/material/icon'; @Component({ selector: 'tb-scada-symbol-widget', @@ -75,6 +76,7 @@ export class ScadaSymbolWidgetComponent implements OnInit, AfterViewInit, OnDest protected imagePipe: ImagePipe, protected sanitizer: DomSanitizer, private imageService: ImageService, + private iconRegistry: MatIconRegistry, protected cd: ChangeDetectorRef) { } @@ -138,7 +140,8 @@ export class ScadaSymbolWidgetComponent implements OnInit, AfterViewInit, OnDest this.noScadaSymbol = true; this.cd.markForCheck(); } else { - this.scadaSymbolObject = new ScadaSymbolObject(rootElement, this.ctx, content, + this.scadaSymbolObject = new ScadaSymbolObject(rootElement, this.ctx, this.iconRegistry, + content, this.settings.scadaSymbolObjectSettings, this, simulated); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts index 263297ee75..8bf3080433 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts @@ -34,7 +34,7 @@ import { mergeDeep, parseFunction } from '@core/utils'; -import { BehaviorSubject, forkJoin, Observable, Observer, Subject } from 'rxjs'; +import { BehaviorSubject, forkJoin, Observable, Observer, of, Subject } from 'rxjs'; import { ValueAction, ValueGetter, ValueSetter } from '@home/components/widget/lib/action/action-widget.models'; import { WidgetContext } from '@home/models/widget-component.models'; import { ColorProcessor, constantColor, Font } from '@shared/models/widget-settings.models'; @@ -42,13 +42,16 @@ import { AttributeScope } from '@shared/models/telemetry/telemetry.models'; import { UtilsService } from '@core/services/utils.service'; import { WidgetAction, WidgetActionType, widgetActionTypeTranslationMap } from '@shared/models/widget.models'; import { ResizeObserver } from '@juggle/resize-observer'; -import { takeUntil } from 'rxjs/operators'; +import { catchError, map, take, takeUntil } from 'rxjs/operators'; +import { isSvgIcon, splitIconName } from '@shared/models/icon.models'; +import { MatIconRegistry } from '@angular/material/icon'; export interface ScadaSymbolApi { generateElementId: () => string; formatValue: (value: any, dec?: number, units?: string, showZeroDecimals?: boolean) => string | undefined; text: (element: Element | Element[], text: string) => void; font: (element: Element | Element[], font: Font, color: string) => void; + icon: (element: Element | Element[], icon: string, size?: number, color?: string, center?: boolean) => void; animate: (element: Element, duration: number) => Runner; resetAnimation: (element: Element) => void; finishAnimation: (element: Element) => void; @@ -133,7 +136,8 @@ export enum ScadaSymbolPropertyType { color = 'color', color_settings = 'color_settings', font = 'font', - units = 'units' + units = 'units', + icon = 'icon' } export const scadaSymbolPropertyTypes = Object.keys(ScadaSymbolPropertyType) as ScadaSymbolPropertyType[]; @@ -146,7 +150,8 @@ export const scadaSymbolPropertyTypeTranslations = new Map { + if (element.type === 'g') { + element.clear(); + this.createIconElement(icon, size, color).subscribe((iconElement) => { + if (iconElement) { + element.add(iconElement); + if (center) { + const box = iconElement.bbox(); + iconElement.translate(-box.cx, -box.cy); + } + } + }); + } + }); + } + + private createIconElement(icon: string, size: number, color: string): Observable { + const isSvg = isSvgIcon(icon); + if (isSvg) { + const [namespace, iconName] = splitIconName(icon); + return this.iconRegistry + .getNamedSvgIcon(iconName, namespace) + .pipe( + take(1), + map((svgElement) => { + const element = new Element(svgElement.firstChild); + const box = element.bbox(); + const scale = size / box.height; + element.scale(scale); + element.fill(color); + return element; + }), + catchError(() => of(null) + )); + } else { + const iconName = splitIconName(icon)[1]; + const textElement = this.svgShape.text(iconName); + const fontSetClasses = ( + this.iconRegistry.getDefaultFontSetClass() + ).filter(className => className.length > 0); + fontSetClasses.forEach(className => textElement.addClass(className)); + textElement.font({size}); + textElement.attr({ + 'text-anchor': 'start', + 'dominant-baseline': 'hanging', + style: `font-size: ${size}px` + }); + textElement.fill(color); + return of(textElement); + } + } + private animate(element: Element, duration: number): Runner { this.finishAnimation(element); return element.animate(duration, 0, 'now'); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/scada/scada-symbol-object-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/scada/scada-symbol-object-settings.component.html index 5b6d50bf1c..1a4d5eb77b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/scada/scada-symbol-object-settings.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/common/scada/scada-symbol-object-settings.component.html @@ -79,6 +79,10 @@ [class]="property.fieldClass" [required]="property.required" formControlName="{{ property.id }}"> + +
diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html index 15322b38d4..6090a9504e 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-panel.component.html @@ -76,6 +76,10 @@ + +
scada.property.number-settings
diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-row.component.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-row.component.ts index 3c5ea6cb07..3da851063f 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-row.component.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/metadata-components/scada-symbol-property-row.component.ts @@ -81,6 +81,8 @@ export const defaultPropertyValue = (type: ScadaSymbolPropertyType): any => { } as Font; case ScadaSymbolPropertyType.units: return ''; + case ScadaSymbolPropertyType.icon: + return 'star'; } }; diff --git a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts index 433e311fb7..9c1ad96894 100644 --- a/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts +++ b/ui-ngx/src/app/modules/home/pages/scada-symbol/scada-symbol-editor.models.ts @@ -491,17 +491,6 @@ export class ScadaSymbolElement { element.show(); } this.box = element.rbox(this.editObject.svgShape); -/* if (element.visible()) { - this.box = element.rbox(this.editObject.svgShape); - if (parentGroup && parentGroup.invisible) { - this.invisible = true; - } - } else { - element.show(); - this.box = element.rbox(this.editObject.svgShape); - element.hide(); - this.invisible = true; - }*/ } public init() { @@ -1297,6 +1286,41 @@ export const scadaSymbolContextCompletion = (metadata: ScadaSymbolMetadata, tags } ] }, + icon: { + meta: 'function', + description: 'Draws icon inside element(s). Only applicable for elements of type ' + + 'SVG.G.', + args: [ + { + name: 'element', + description: 'SVG element or an array of SVG elements', + type: 'Element | Array<Element>' + }, + { + name: 'icon', + description: 'Icon to draw', + type: 'string' + }, + { + name: 'size', + description: 'Optional icon size in pixels. Default 12 pixels.', + type: 'number', + optional: true + }, + { + name: 'color', + description: 'Optional icon color. Default #0000008A.', + type: 'string', + optional: true + }, + { + name: 'center', + description: 'Whether to center icon inside group element. Default true.', + type: 'boolean', + optional: true + } + ] + }, disable: { meta: 'function', description: 'Disables element(s). Disabled element doesn\'t accept any user interaction. ' + @@ -1417,6 +1441,8 @@ const scadaSymbolPropertyCompletionType = (type: ScadaSymbolPropertyType): strin return 'Font'; case ScadaSymbolPropertyType.units: return 'units string'; + case ScadaSymbolPropertyType.icon: + return 'icon string'; } }; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 2b5a33a9b3..37ea4a1a87 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3746,6 +3746,7 @@ "type-color-settings": "Color settings", "type-font": "Font", "type-units": "Units", + "type-icon": "Icon", "no-properties": "No properties configured", "add-property": "Add property", "property-settings": "Property settings", From 949b2c5f2e2c0b999eaf46d34a69fc94c2d0056c Mon Sep 17 00:00:00 2001 From: mpetrov Date: Wed, 11 Sep 2024 17:46:06 +0300 Subject: [PATCH 74/80] [3969] refactoring --- .../resources-library-table-config.resolve.ts | 5 ++++- .../resource/resources-library.component.ts | 16 ++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts index 1e7eef1c41..148a47feac 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts @@ -22,7 +22,7 @@ import { EntityTableConfig } from '@home/models/entity/entities-table-config.models'; import { Resolve, Router } from '@angular/router'; -import { Resource, ResourceInfo, ResourceTypeTranslationMap } from '@shared/models/resource.models'; +import { Resource, ResourceInfo, ResourceType, ResourceTypeTranslationMap } from '@shared/models/resource.models'; import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models'; import { NULL_UUID } from '@shared/models/id/has-uuid'; import { DatePipe } from '@angular/common'; @@ -150,6 +150,9 @@ export class ResourcesLibraryTableConfigResolver implements Resolve impleme updateForm(entity: Resource): void { const { resourceType, fileName, title, data } = entity; - this.updateTableReadonlyConfig(); + this.entityForm.patchValue({ resourceType, fileName, title, data }); + } - if (this.isEdit) { + override updateFormState(): void { + super.updateFormState(); + if (this.isEdit && this.entityForm) { this.entityForm.get('resourceType').disable({ emitEvent: false }); - if (resourceType !== ResourceType.JS_MODULE) { + if (this.entityForm.get('resourceType').value !== ResourceType.JS_MODULE) { this.entityForm.get('fileName').disable({ emitEvent: false }); } } - - this.entityForm.patchValue({ resourceType, fileName, title, data }); } prepareFormValue(formValue: Resource): Resource { @@ -138,11 +139,6 @@ export class ResourcesLibraryComponent extends EntityComponent impleme })); } - private updateTableReadonlyConfig(): void { - this.entitiesTableConfigValue.detailsReadonly = () => - this.resourceType.LWM2M_MODEL === this.entityForm.get('resourceType').value; - } - private observeResourceTypeChange(): void { this.entityForm.get('resourceType').valueChanges.pipe( startWith(ResourceType.JS_MODULE), From d993b0163840c726eeacce62ae63f86852e1f3df Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Wed, 11 Sep 2024 18:40:08 +0300 Subject: [PATCH 75/80] UI: Improve SCADA symbol icon function. --- .../widget/lib/scada/scada-symbol.models.ts | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts index 8bf3080433..1163351fb8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts @@ -883,16 +883,27 @@ export class ScadaSymbolObject { center = true) { this.elements(e).forEach(element => { if (element.type === 'g') { - element.clear(); - this.createIconElement(icon, size, color).subscribe((iconElement) => { - if (iconElement) { - element.add(iconElement); - if (center) { - const box = iconElement.bbox(); - iconElement.translate(-box.cx, -box.cy); - } + let skip = false; + const firstChild = element.first(); + if (firstChild) { + const iconData: {icon: string; size: number; color: string} = firstChild.remember('iconData'); + if (iconData && iconData.icon === icon && iconData.size === size && iconData.color === color) { + skip = true; } - }); + } + if (!skip) { + element.clear(); + this.createIconElement(icon, size, color).subscribe((iconElement) => { + if (iconElement) { + iconElement.remember('iconData', {icon, size, color}); + element.add(iconElement); + if (center) { + const box = iconElement.bbox(); + iconElement.translate(-box.cx, -box.cy); + } + } + }); + } } }); } From 358374ab697564d7e91f5ce8233dc13c94fef1ca Mon Sep 17 00:00:00 2001 From: mpetrov Date: Wed, 11 Sep 2024 18:44:53 +0300 Subject: [PATCH 76/80] [3969] table actions disabled fix --- .../resource/resources-library-table-config.resolve.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts index 148a47feac..74535ca413 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts @@ -118,7 +118,7 @@ export class ResourcesLibraryTableConfigResolver implements Resolve this.isResourceEditable(resource, authUser.authority); this.config.entitySelectionEnabled = (resource) => this.isResourceEditable(resource, authUser.authority); - this.config.detailsReadonly = (resource) => !this.isResourceEditable(resource, authUser.authority); + this.config.detailsReadonly = (resource) => !this.isResourceEditable(resource, authUser.authority, true); return this.config; } @@ -149,8 +149,8 @@ export class ResourcesLibraryTableConfigResolver implements Resolve Date: Wed, 11 Sep 2024 19:08:21 +0300 Subject: [PATCH 77/80] [4054] fixed otaPackage api call in accordance with documentation --- ui-ngx/src/app/core/http/ota-package.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/core/http/ota-package.service.ts b/ui-ngx/src/app/core/http/ota-package.service.ts index 9952dd4916..de062a94ee 100644 --- a/ui-ngx/src/app/core/http/ota-package.service.ts +++ b/ui-ngx/src/app/core/http/ota-package.service.ts @@ -59,7 +59,7 @@ export class OtaPackageService { } public getOtaPackage(otaPackageId: string, config?: RequestConfig): Observable { - return this.http.get(`/api/otaPackages/${otaPackageId}`, defaultHttpOptionsFromConfig(config)); + return this.http.get(`/api/otaPackage/${otaPackageId}`, defaultHttpOptionsFromConfig(config)); } public getOtaPackageInfo(otaPackageId: string, config?: RequestConfig): Observable { From 4bad947bad8bd99a4eec434b59ba91e8a761e149 Mon Sep 17 00:00:00 2001 From: Artem Dzhereleiko Date: Thu, 12 Sep 2024 09:30:55 +0300 Subject: [PATCH 78/80] UI: Fixed behavior --- .../data/json/system/scada_symbols/vertical-ball-valve.svg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/src/main/data/json/system/scada_symbols/vertical-ball-valve.svg b/application/src/main/data/json/system/scada_symbols/vertical-ball-valve.svg index 3aee266486..f284c7f86d 100644 --- a/application/src/main/data/json/system/scada_symbols/vertical-ball-valve.svg +++ b/application/src/main/data/json/system/scada_symbols/vertical-ball-valve.svg @@ -93,7 +93,7 @@ }, "valueToData": { "type": "CONSTANT", - "constantValue": false, + "constantValue": true, "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" } }, @@ -127,7 +127,7 @@ }, "valueToData": { "type": "CONSTANT", - "constantValue": true, + "constantValue": false, "valueToDataFunction": "/* Convert input boolean value to RPC parameters or attribute/time-series value */\nreturn value;" } }, From b49bf05e45d549ef2f08a024c7ce3cd756026465 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 12 Sep 2024 09:31:07 +0300 Subject: [PATCH 79/80] UI: Minor fix. --- .../home/components/widget/lib/scada/scada-symbol.models.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts index 1163351fb8..8e5993902d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/scada/scada-symbol.models.ts @@ -933,7 +933,7 @@ export class ScadaSymbolObject { this.iconRegistry.getDefaultFontSetClass() ).filter(className => className.length > 0); fontSetClasses.forEach(className => textElement.addClass(className)); - textElement.font({size}); + textElement.font({size: `${size}px`}); textElement.attr({ 'text-anchor': 'start', 'dominant-baseline': 'hanging', From 0def9aed9b2d1f099d06c2b8ceabdfd413567f8b Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 12 Sep 2024 09:40:24 +0300 Subject: [PATCH 80/80] UI: Refactoring resources-library improvement readonly --- .../resources-library-table-config.resolve.ts | 12 ++++++++---- .../admin/resource/resources-library.component.ts | 3 +-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts index 74535ca413..66a704996b 100644 --- a/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts +++ b/ui-ngx/src/app/modules/home/pages/admin/resource/resources-library-table-config.resolve.ts @@ -118,7 +118,7 @@ export class ResourcesLibraryTableConfigResolver implements Resolve this.isResourceEditable(resource, authUser.authority); this.config.entitySelectionEnabled = (resource) => this.isResourceEditable(resource, authUser.authority); - this.config.detailsReadonly = (resource) => !this.isResourceEditable(resource, authUser.authority, true); + this.config.detailsReadonly = (resource) => this.detailsReadonly(resource, authUser.authority); return this.config; } @@ -149,10 +149,14 @@ export class ResourcesLibraryTableConfigResolver implements Resolve impleme } updateForm(entity: Resource): void { - const { resourceType, fileName, title, data } = entity; - this.entityForm.patchValue({ resourceType, fileName, title, data }); + this.entityForm.patchValue(entity); } override updateFormState(): void {