From f1083098116a450cb85970a5953a300d0c1b50ca Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 7 Jan 2025 19:07:33 +0200 Subject: [PATCH 01/13] UI: Move rule node config to TB --- .../engine/action/TbAssignToCustomerNode.java | 1 - .../rule/engine/action/TbClearAlarmNode.java | 1 - .../TbCopyAttributesToEntityViewNode.java | 1 - .../rule/engine/action/TbCreateAlarmNode.java | 1 - .../engine/action/TbCreateRelationNode.java | 1 - .../engine/action/TbDeleteRelationNode.java | 1 - .../rule/engine/action/TbDeviceStateNode.java | 1 - .../rule/engine/action/TbLogNode.java | 1 - .../rule/engine/action/TbMsgCountNode.java | 1 - .../TbSaveToCustomCassandraTableNode.java | 1 - .../action/TbUnassignFromCustomerNode.java | 1 - .../engine/aws/lambda/TbAwsLambdaNode.java | 1 - .../rule/engine/aws/sns/TbSnsNode.java | 1 - .../rule/engine/aws/sqs/TbSqsNode.java | 1 - .../rule/engine/debug/TbMsgGeneratorNode.java | 1 - .../deduplication/TbMsgDeduplicationNode.java | 1 - .../rule/engine/delay/TbMsgDelayNode.java | 1 - .../engine/edge/TbMsgPushToCloudNode.java | 1 - .../rule/engine/edge/TbMsgPushToEdgeNode.java | 1 - .../engine/filter/TbAssetTypeSwitchNode.java | 1 - .../engine/filter/TbCheckAlarmStatusNode.java | 1 - .../engine/filter/TbCheckMessageNode.java | 1 - .../engine/filter/TbCheckRelationNode.java | 1 - .../engine/filter/TbDeviceTypeSwitchNode.java | 1 - .../rule/engine/filter/TbJsFilterNode.java | 1 - .../rule/engine/filter/TbJsSwitchNode.java | 1 - .../engine/filter/TbMsgTypeFilterNode.java | 1 - .../engine/filter/TbMsgTypeSwitchNode.java | 1 - .../filter/TbOriginatorTypeFilterNode.java | 1 - .../filter/TbOriginatorTypeSwitchNode.java | 1 - .../rule/engine/flow/TbAckNode.java | 1 - .../rule/engine/flow/TbCheckpointNode.java | 1 - .../engine/flow/TbRuleChainInputNode.java | 1 - .../engine/flow/TbRuleChainOutputNode.java | 1 - .../rule/engine/gcp/pubsub/TbPubSubNode.java | 1 - .../engine/geo/TbGpsGeofencingActionNode.java | 1 - .../engine/geo/TbGpsGeofencingFilterNode.java | 1 - .../rule/engine/kafka/TbKafkaNode.java | 1 - .../rule/engine/mail/TbMsgToEmailNode.java | 1 - .../rule/engine/mail/TbSendEmailNode.java | 1 - .../rule/engine/math/TbMathNode.java | 1 - .../engine/metadata/CalculateDeltaNode.java | 1 - .../TbFetchDeviceCredentialsNode.java | 1 - .../engine/metadata/TbGetAttributesNode.java | 1 - .../metadata/TbGetCustomerAttributeNode.java | 1 - .../metadata/TbGetCustomerDetailsNode.java | 1 - .../engine/metadata/TbGetDeviceAttrNode.java | 1 - .../metadata/TbGetOriginatorFieldsNode.java | 1 - .../metadata/TbGetRelatedAttributeNode.java | 1 - .../engine/metadata/TbGetTelemetryNode.java | 1 - .../metadata/TbGetTenantAttributeNode.java | 1 - .../metadata/TbGetTenantDetailsNode.java | 1 - .../rule/engine/mqtt/TbMqttNode.java | 1 - .../engine/mqtt/azure/TbAzureIotHubNode.java | 1 - .../notification/TbNotificationNode.java | 1 - .../rule/engine/notification/TbSlackNode.java | 1 - .../engine/profile/TbDeviceProfileNode.java | 1 - .../rule/engine/rabbitmq/TbRabbitMqNode.java | 1 - .../rule/engine/rest/TbRestApiCallNode.java | 1 - .../rest/TbSendRestApiCallReplyNode.java | 1 - .../rule/engine/rpc/TbSendRPCReplyNode.java | 1 - .../rule/engine/rpc/TbSendRPCRequestNode.java | 1 - .../rule/engine/sms/TbSendSmsNode.java | 1 - .../engine/telemetry/TbMsgAttributesNode.java | 1 - .../telemetry/TbMsgDeleteAttributesNode.java | 1 - .../engine/telemetry/TbMsgTimeseriesNode.java | 1 - .../TbSynchronizationBeginNode.java | 1 - .../transaction/TbSynchronizationEndNode.java | 1 - .../transform/TbChangeOriginatorNode.java | 1 - .../rule/engine/transform/TbCopyKeysNode.java | 1 - .../engine/transform/TbDeleteKeysNode.java | 1 - .../rule/engine/transform/TbJsonPathNode.java | 1 - .../engine/transform/TbRenameKeysNode.java | 1 - .../engine/transform/TbSplitArrayMsgNode.java | 1 - .../engine/transform/TbTransformMsgNode.java | 1 - .../assign-customer-config.component.html | 35 + .../assign-customer-config.component.ts | 49 + .../action/attributes-config.component.html | 79 ++ .../action/attributes-config.component.ts | 62 ++ .../action/clear-alarm-config.component.html | 67 ++ .../action/clear-alarm-config.component.ts | 127 +++ .../action/create-alarm-config.component.html | 128 +++ .../action/create-alarm-config.component.ts | 199 ++++ .../create-relation-config.component.html | 100 ++ .../create-relation-config.component.ts | 107 +++ .../delete-attributes-config.component.html | 89 ++ .../delete-attributes-config.component.ts | 88 ++ .../delete-relation-config.component.html | 62 ++ .../delete-relation-config.component.ts | 101 ++ .../device-profile-config.component.html | 32 + .../action/device-profile-config.component.ts | 59 ++ .../action/device-state-config.component.html | 27 + .../action/device-state-config.component.ts | 59 ++ .../action/generator-config.component.html | 117 +++ .../action/generator-config.component.scss | 51 ++ .../action/generator-config.component.ts | 155 ++++ .../gps-geo-action-config.component.html | 195 ++++ .../gps-geo-action-config.component.scss | 20 + .../action/gps-geo-action-config.component.ts | 126 +++ .../action/log-config.component.html | 59 ++ .../rule-node/action/log-config.component.ts | 124 +++ .../math-function-config.component.html | 103 +++ .../math-function-config.component.scss | 41 + .../action/math-function-config.component.ts | 92 ++ .../action/msg-count-config.component.html | 36 + .../action/msg-count-config.component.ts | 45 + .../action/msg-delay-config.component.html | 57 ++ .../action/msg-delay-config.component.ts | 65 ++ .../push-to-cloud-config.component.html | 49 + .../action/push-to-cloud-config.component.ts | 48 + .../action/push-to-edge-config.component.html | 49 + .../action/push-to-edge-config.component.ts | 48 + .../action/rpc-reply-config.component.html | 36 + .../action/rpc-reply-config.component.ts | 45 + .../action/rpc-request-config.component.html | 29 + .../action/rpc-request-config.component.ts | 43 + .../action/rule-node-config-action.module.ts | 132 +++ ...save-to-custom-table-config.component.html | 56 ++ .../save-to-custom-table-config.component.ts | 50 + ...-rest-api-call-reply-config.component.html | 32 + ...nd-rest-api-call-reply-config.component.ts | 44 + .../action/timeseries-config.component.html | 50 + .../action/timeseries-config.component.ts | 45 + .../unassign-customer-config.component.html | 39 + .../unassign-customer-config.component.ts | 72 ++ .../common/alarm-status-select.component.html | 37 + .../common/alarm-status-select.component.scss | 60 ++ .../common/alarm-status-select.component.ts | 83 ++ .../arguments-map-config.component.html | 129 +++ .../arguments-map-config.component.scss | 27 + .../common/arguments-map-config.component.ts | 242 +++++ .../common/credentials-config.component.html | 95 ++ .../common/credentials-config.component.ts | 252 +++++ ...vice-relations-query-config.component.html | 66 ++ ...vice-relations-query-config.component.scss | 20 + ...device-relations-query-config.component.ts | 108 +++ .../common/example-hint.component.html | 29 + .../common/example-hint.component.scss | 31 + .../common/example-hint.component.ts | 32 + .../common/kv-map-config-old.component.html | 70 ++ .../common/kv-map-config-old.component.scss | 59 ++ .../common/kv-map-config-old.component.ts | 198 ++++ .../common/kv-map-config.component.html | 72 ++ .../common/kv-map-config.component.scss | 24 + .../common/kv-map-config.component.ts | 240 +++++ .../math-function-autocomplete.component.html | 43 + .../math-function-autocomplete.component.ts | 152 +++ .../message-types-config.component.html | 71 ++ .../common/message-types-config.component.ts | 239 +++++ .../common/msg-metadata-chip.component.html | 26 + .../common/msg-metadata-chip.component.ts | 96 ++ ...t-message-type-autocomplete.component.html | 50 + ...put-message-type-autocomplete.component.ts | 178 ++++ .../relations-query-config-old.component.html | 45 + .../relations-query-config-old.component.ts | 99 ++ .../relations-query-config.component.html | 61 ++ .../relations-query-config.component.ts | 98 ++ .../common/rule-node-config-common.module.ts | 80 ++ .../common/select-attributes.component.html | 59 ++ .../common/select-attributes.component.ts | 139 +++ .../common/sv-map-config.component.html | 70 ++ .../common/sv-map-config.component.scss | 24 + .../common/sv-map-config.component.ts | 266 ++++++ .../rule-node/empty-config.component.ts | 42 + .../calculate-delta-config.component.html | 92 ++ .../calculate-delta-config.component.ts | 87 ++ .../customer-attributes-config.component.html | 46 + .../customer-attributes-config.component.scss | 23 + .../customer-attributes-config.component.ts | 100 ++ .../device-attributes-config.component.html | 46 + .../device-attributes-config.component.ts | 77 ++ .../entity-details-config.component.html | 35 + .../entity-details-config.component.ts | 87 ++ ...h-device-credentials-config.component.html | 23 + ...tch-device-credentials-config.component.ts | 51 ++ ...emetry-from-database-config.component.html | 182 ++++ ...emetry-from-database-config.component.scss | 66 ++ ...elemetry-from-database-config.component.ts | 205 +++++ ...riginator-attributes-config.component.html | 40 + .../originator-attributes-config.component.ts | 75 ++ .../originator-fields-config.component.html | 41 + .../originator-fields-config.component.ts | 67 ++ .../related-attributes-config.component.html | 62 ++ .../related-attributes-config.component.ts | 160 ++++ .../rule-node-core-enrichment.module.ts | 77 ++ .../tenant-attributes-config.component.html | 45 + .../tenant-attributes-config.component.scss | 21 + .../tenant-attributes-config.component.ts | 91 ++ .../azure-iot-hub-config.component.html | 122 +++ .../azure-iot-hub-config.component.ts | 117 +++ .../external/kafka-config.component.html | 111 +++ .../external/kafka-config.component.ts | 79 ++ .../external/lambda-config.component.html | 115 +++ .../external/lambda-config.component.ts | 50 + .../external/mqtt-config.component.html | 85 ++ .../external/mqtt-config.component.scss | 20 + .../external/mqtt-config.component.ts | 71 ++ .../notification-config.component.html | 34 + .../external/notification-config.component.ts | 48 + .../external/pubsub-config.component.html | 53 ++ .../external/pubsub-config.component.ts | 47 + .../external/rabbit-mq-config.component.html | 96 ++ .../external/rabbit-mq-config.component.ts | 64 ++ .../rest-api-call-config.component.html | 130 +++ .../rest-api-call-config.component.ts | 95 ++ .../rule-node-config-external.module.ts | 91 ++ .../external/send-email-config.component.html | 116 +++ .../external/send-email-config.component.ts | 95 ++ .../external/send-sms-config.component.html | 43 + .../external/send-sms-config.component.ts | 61 ++ .../external/slack-config.component.html | 49 + .../external/slack-config.component.scss | 43 + .../external/slack-config.component.ts | 64 ++ .../external/sns-config.component.html | 48 + .../external/sns-config.component.ts | 46 + .../external/sqs-config.component.html | 76 ++ .../external/sqs-config.component.ts | 54 ++ .../filter/check-alarm-status.component.html | 29 + .../filter/check-alarm-status.component.ts | 52 ++ .../check-message-config.component.html | 45 + .../filter/check-message-config.component.ts | 78 ++ .../check-relation-config.component.html | 55 ++ .../check-relation-config.component.scss | 20 + .../filter/check-relation-config.component.ts | 77 ++ .../gps-geo-filter-config.component.html | 126 +++ .../gps-geo-filter-config.component.scss | 20 + .../filter/gps-geo-filter-config.component.ts | 121 +++ .../filter/message-type-config.component.html | 24 + .../filter/message-type-config.component.ts | 51 ++ .../originator-type-config.component.html | 31 + .../originator-type-config.component.ts | 65 ++ .../filter/rule-node-config-filter.module.ts | 69 ++ .../filter/script-config.component.html | 57 ++ .../filter/script-config.component.ts | 128 +++ .../filter/switch-config.component.html | 57 ++ .../filter/switch-config.component.ts | 130 +++ .../flow/rule-chain-input.component.html | 33 + .../flow/rule-chain-input.component.ts | 48 + .../flow/rule-chain-output.component.html | 20 + .../flow/rule-chain-output.component.ts | 42 + .../flow/rule-node-config-flow.module.ts | 43 + .../rule-node/rule-node-config.models.ts | 862 ++++++++++++++++++ .../rule-node/rule-node-config.module.ts | 75 ++ .../change-originator-config.component.html | 66 ++ .../change-originator-config.component.ts | 83 ++ .../transform/copy-keys-config.component.html | 36 + .../transform/copy-keys-config.component.ts | 73 ++ .../deduplication-config.component.html | 100 ++ .../deduplication-config.component.ts | 79 ++ .../delete-keys-config.component.html | 35 + .../transform/delete-keys-config.component.ts | 74 ++ .../node-json-path-config.component.html | 25 + .../node-json-path-config.component.ts | 44 + .../rename-keys-config.component.html | 40 + .../rename-keys-config.component.scss | 27 + .../transform/rename-keys-config.component.ts | 73 ++ .../rule-node-config-transform.module.ts | 70 ++ .../transform/script-config.component.html | 59 ++ .../transform/script-config.component.ts | 128 +++ .../transform/to-email-config.component.html | 139 +++ .../transform/to-email-config.component.scss | 29 + .../transform/to-email-config.component.ts | 98 ++ .../rulechain/rule-node-config.component.ts | 14 +- .../home/pages/rulechain/rulechain.module.ts | 4 +- .../src/app/shared/models/rule-node.models.ts | 8 +- .../assets/locale/locale.constant-en_US.json | 728 +++++++++++++++ 266 files changed, 15639 insertions(+), 83 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/rule-node-config-action.module.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/rule-node-config-common.module.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/empty-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/rule-node-core-enrichment.module.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/rule-node-config-external.module.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/rule-node-config-filter.module.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/flow/rule-node-config-flow.module.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.models.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/rule-node-config-transform.module.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.ts create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.html create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.scss create mode 100644 ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.ts diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java index 01dd176896..d6afd971b4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java @@ -40,7 +40,6 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDescription = "Assign message originator entity to customer", nodeDetails = "Finds target customer by title and assign message originator entity to this customer. " + "Rule node will create a new customer if it doesn't exist, and 'Create new customer if it doesn't exist' enabled.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeAssignToCustomerConfig", icon = "add_circle", version = 1 diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java index 622448f494..55ba8ae59a 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbClearAlarmNode.java @@ -43,7 +43,6 @@ import org.thingsboard.server.common.msg.TbMsg; "If alarm was not cleared, original message is returned. Otherwise new Message returned with type 'ALARM', Alarm object in 'msg' property and 'metadata' will contains 'isClearedAlarm' property. " + "Message payload can be accessed via msg property. For example 'temperature = ' + msg.temperature ;. " + "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeClearAlarmConfig", icon = "notifications_off" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java index a4b0227551..1a1bcf7daf 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java @@ -63,7 +63,6 @@ import static org.thingsboard.server.common.data.msg.TbNodeConnectionType.SUCCES nodeDetails = "Copy attributes from asset/device to related entity view according to entity view configuration. \n " + "Copy will be done only for attributes that are between start and end dates and according to attribute keys configuration. \n" + "Changes message originator to related entity view and produces new messages according to count of updated entity views", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig", icon = "content_copy" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java index 7e535596cd..c1e8ae89aa 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java @@ -51,7 +51,6 @@ import java.util.List; "If alarm was not created, original message is returned. Otherwise new Message returned with type 'ALARM', Alarm object in 'msg' property and 'metadata' will contains one of those properties 'isNewAlarm/isExistingAlarm'. " + "Message payload can be accessed via msg property. For example 'temperature = ' + msg.temperature ;. " + "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeCreateAlarmConfig", icon = "notifications_active" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java index 7571695b49..0ae90cd6a7 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java @@ -61,7 +61,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "Useful in GPS tracking use cases where relation acts as a temporary indicator of a tracker presence in specific geofence." + "
  • Change originator to target entity - useful when you need to process submitted message as a message from target entity.
  • " + "Output connections: Success - if the relation already exists or successfully created, otherwise Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeCreateRelationConfig", icon = "add_circle", version = 1 diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java index dbc914065f..abbaad7cb3 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java @@ -53,7 +53,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "
  • User - use a user with the specified email as the target entity to delete relation with.
  • " + "
  • Edge - use an edge with the specified name as the target entity to delete relation with.
  • " + "Output connections: Success - If the relation(s) successfully deleted, otherwise Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeDeleteRelationConfig", icon = "remove_circle", version = 1 diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNode.java index 7925178b33..b00023e59d 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeviceStateNode.java @@ -58,7 +58,6 @@ import java.util.Set; "This node is particularly useful when device isn't using transports to receive data, such as when fetching data from external API or computing new data within the rule chain.", configClazz = TbDeviceStateNodeConfiguration.class, relationTypes = {TbNodeConnectionType.SUCCESS, TbNodeConnectionType.FAILURE, "Rate limited"}, - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeDeviceStateConfig" ) public class TbDeviceStateNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java index 6b07d41a42..cdbaca491e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbLogNode.java @@ -43,7 +43,6 @@ import java.util.Objects; nodeDetails = "Transform incoming Message with configured JS function to String and log final value into Thingsboard log file. " + "Message payload can be accessed via msg property. For example 'temperature = ' + msg.temperature ;. " + "Message metadata can be accessed via metadata property. For example 'name = ' + metadata.customerName;.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeLogConfig", icon = "menu" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java index edbd9c7ca4..b387877f07 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbMsgCountNode.java @@ -42,7 +42,6 @@ import java.util.concurrent.atomic.AtomicLong; nodeDescription = "Count incoming messages", nodeDetails = "Count incoming messages for specified interval and produces POST_TELEMETRY_REQUEST msg with messages count", icon = "functions", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeMsgCountConfig" ) public class TbMsgCountNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java index a0dbc5da97..5c485353ab 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbSaveToCustomCassandraTableNode.java @@ -69,7 +69,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "Note:If the mapping key is $entity_id, that is identified by the Message Originator, then to the appropriate column name(mapping value) will be write the message originator id.

    " + "If specified message field does not exist or is not a JSON Primitive, the outbound message will be routed via failure chain," + " otherwise, the message will be routed via success chain.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeCustomTableConfig", icon = "file_upload", ruleChainTypes = RuleChainType.CORE) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java index 93fbe8019e..9569d0be77 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbUnassignFromCustomerNode.java @@ -42,7 +42,6 @@ import org.thingsboard.server.common.msg.TbMsg; "If the incoming message originator is a dashboard, will try to search for the customer by title specified in the configuration. " + "If customer doesn't exist, the exception will be thrown. Otherwise will unassign the dashboard from retrieved customer.

    " + "Other entities can be assigned only to one customer, so specified customer title in the configuration will be ignored if the originator isn't a dashboard.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeUnAssignToCustomerConfig", icon = "remove_circle", version = 1 diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNode.java index bb9f5416db..6cf01f80c7 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/lambda/TbAwsLambdaNode.java @@ -53,7 +53,6 @@ import static org.thingsboard.server.dao.service.ConstraintValidator.validateFie "It sends messages using a RequestResponse invocation type. " + "The node uses a pre-configured client and specified function to run.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeLambdaConfig", iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java index 2c732150e1..3a9733ee82 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sns/TbSnsNode.java @@ -46,7 +46,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; nodeDetails = "Will publish message payload to the AWS SNS topic. Outbound message will contain response fields " + "(messageId, requestId) in the Message Metadata from the AWS SNS. " + "For example requestId field can be accessed with metadata.requestId.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeSnsConfig", iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java index e61cd537c4..d9b6120fc7 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/aws/sqs/TbSqsNode.java @@ -52,7 +52,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "response fields (messageId, requestId, messageBodyMd5, messageAttributesMd5" + ", sequenceNumber) in the Message Metadata from the AWS SQS." + " For example requestId field can be accessed with metadata.requestId.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeSqsConfig", iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4Ij48cGF0aCBkPSJNMTMuMjMgMTAuNTZWMTBjLTEuOTQgMC0zLjk5LjM5LTMuOTkgMi42NyAwIDEuMTYuNjEgMS45NSAxLjYzIDEuOTUuNzYgMCAxLjQzLS40NyAxLjg2LTEuMjIuNTItLjkzLjUtMS44LjUtMi44NG0yLjcgNi41M2MtLjE4LjE2LS40My4xNy0uNjMuMDYtLjg5LS43NC0xLjA1LTEuMDgtMS41NC0xLjc5LTEuNDcgMS41LTIuNTEgMS45NS00LjQyIDEuOTUtMi4yNSAwLTQuMDEtMS4zOS00LjAxLTQuMTcgMC0yLjE4IDEuMTctMy42NCAyLjg2LTQuMzggMS40Ni0uNjQgMy40OS0uNzYgNS4wNC0uOTNWNy41YzAtLjY2LjA1LTEuNDEtLjMzLTEuOTYtLjMyLS40OS0uOTUtLjctMS41LS43LTEuMDIgMC0xLjkzLjUzLTIuMTUgMS42MS0uMDUuMjQtLjI1LjQ4LS40Ny40OWwtMi42LS4yOGMtLjIyLS4wNS0uNDYtLjIyLS40LS41Ni42LTMuMTUgMy40NS00LjEgNi00LjEgMS4zIDAgMyAuMzUgNC4wMyAxLjMzQzE3LjExIDQuNTUgMTcgNi4xOCAxNyA3Ljk1djQuMTdjMCAxLjI1LjUgMS44MSAxIDIuNDguMTcuMjUuMjEuNTQgMCAuNzFsLTIuMDYgMS43OGgtLjAxIj48L3BhdGg+PHBhdGggZD0iTTIwLjE2IDE5LjU0QzE4IDIxLjE0IDE0LjgyIDIyIDEyLjEgMjJjLTMuODEgMC03LjI1LTEuNDEtOS44NS0zLjc2LS4yLS4xOC0uMDItLjQzLjI1LS4yOSAyLjc4IDEuNjMgNi4yNSAyLjYxIDkuODMgMi42MSAyLjQxIDAgNS4wNy0uNSA3LjUxLTEuNTMuMzctLjE2LjY2LjI0LjMyLjUxIj48L3BhdGg+PHBhdGggZD0iTTIxLjA3IDE4LjVjLS4yOC0uMzYtMS44NS0uMTctMi41Ny0uMDgtLjE5LjAyLS4yMi0uMTYtLjAzLS4zIDEuMjQtLjg4IDMuMjktLjYyIDMuNTMtLjMzLjI0LjMtLjA3IDIuMzUtMS4yNCAzLjMyLS4xOC4xNi0uMzUuMDctLjI2LS4xMS4yNi0uNjcuODUtMi4xNC41Ny0yLjV6Ij48L3BhdGg+PC9zdmc+" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java index c7bf1423f8..0fcabd806a 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/debug/TbMsgGeneratorNode.java @@ -62,7 +62,6 @@ import static org.thingsboard.server.common.data.DataConstants.QUEUE_NAME; nodeDescription = "Periodically generates messages", nodeDetails = "Generates messages with configurable period. Javascript function used for message generation.", inEnabled = false, - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeGeneratorConfig", icon = "repeat" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java index cf4b5b4ce1..891efec861 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java @@ -59,7 +59,6 @@ import static org.thingsboard.server.common.data.DataConstants.QUEUE_NAME; "
  • ALL - return all messages as a single JSON array message. " + "Where each element represents object with msg and metadata inner properties.
  • ", icon = "content_copy", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeMsgDeduplicationConfig" ) @Slf4j diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java index a8a2c4e9b5..eb18bd13fe 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/delay/TbMsgDelayNode.java @@ -45,7 +45,6 @@ import java.util.concurrent.TimeUnit; "Deprecated because the acknowledged message still stays in memory (to be delayed) and this " + "does not guarantee that message will be processed even if the \"retry failures and timeouts\" processing strategy will be chosen.", icon = "pause", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeMsgDelayConfig" ) public class TbMsgDelayNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToCloudNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToCloudNode.java index 1ed2f8e849..50355632a3 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToCloudNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToCloudNode.java @@ -46,7 +46,6 @@ import java.util.UUID; "
    ALARM

    " + "Message will be routed via Failure route if node was not able to save cloud event to database or unsupported originator type/message type arrived. " + "In case successful storage cloud event to database message will be routed via Success route.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodePushToCloudConfig", icon = "cloud_upload", ruleChainTypes = RuleChainType.EDGE diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java index 4ae86742a2..2659bb281e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java @@ -61,7 +61,6 @@ import static org.thingsboard.server.dao.edge.BaseRelatedEdgesService.RELATED_ED "
    ALARM

    " + "Message will be routed via Failure route if node was not able to save edge event to database or unsupported message type arrived. " + "In case successful storage edge event to database message will be routed via Success route.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodePushToEdgeConfig", icon = "cloud_download", ruleChainTypes = RuleChainType.CORE diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java index 0fc03be83b..b0f5552b72 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java @@ -36,7 +36,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType; nodeDescription = "Route incoming messages based on the name of the asset profile", nodeDetails = "Route incoming messages based on the name of the asset profile. The asset profile name is case-sensitive.

    " + "Output connections: Asset profile name or Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig") public class TbAssetTypeSwitchNode extends TbAbstractTypeSwitchNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java index ed703e8661..6aa05007d1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java @@ -43,7 +43,6 @@ import java.util.Objects; nodeDescription = "Checks alarm status.", nodeDetails = "Checks the alarm status to match one of the specified statuses.

    " + "Output connections: True, False, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeCheckAlarmStatusConfig") public class TbCheckAlarmStatusNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java index 1b9f2f2a78..0ca3f74d29 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java @@ -40,7 +40,6 @@ import java.util.Map; nodeDetails = "By default, the rule node checks that all specified fields are present. " + "Uncheck the 'Check that all selected fields are present' if the presence of at least one field is sufficient.

    " + "Output connections: True, False, Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeCheckMessageConfig") public class TbCheckMessageNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java index 0356548a03..f24312dba9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java @@ -56,7 +56,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "Otherwise, the rule node checks the presence of a relation to any entity. " + "In both cases, relation lookup is based on configured direction and type.

    " + "Output connections: True, False, Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeCheckRelationConfig") public class TbCheckRelationNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java index d440969fff..a7ec1e86a4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java @@ -36,7 +36,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType; nodeDescription = "Route incoming messages based on the name of the device profile", nodeDetails = "Route incoming messages based on the name of the device profile. The device profile name is case-sensitive

    " + "Output connections: Device profile name or Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig") public class TbDeviceTypeSwitchNode extends TbAbstractTypeSwitchNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java index 6d5aaa6477..767c2f91d6 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java @@ -44,7 +44,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; "Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';
    " + "Message type can be accessed via msgType property.

    " + "Output connections: True, False, Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeScriptConfig" ) public class TbJsFilterNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java index e866f05bd0..10277d067b 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java @@ -46,7 +46,6 @@ import java.util.Set; "Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';
    " + "Message type can be accessed via msgType property.

    " + "Output connections: Custom connection(s) defined by switch node or Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeSwitchConfig") public class TbJsSwitchNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java index 579b6a3ec7..d818c3a8f1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeFilterNode.java @@ -38,7 +38,6 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDescription = "Filter incoming messages by Message Type", nodeDetails = "If incoming message type is expected - send Message via True chain, otherwise False chain is used.

    " + "Output connections: True, False, Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeMessageTypeConfig") public class TbMsgTypeFilterNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java index 971ab22588..455bf2f78c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbMsgTypeSwitchNode.java @@ -36,7 +36,6 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDetails = "Sends messages with message types \"Post attributes\", \"Post telemetry\", \"RPC Request\"" + " etc. via corresponding chain, otherwise Other chain is used.

    " + "Output connections: Message type connection, Other - if message type is custom or Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig") public class TbMsgTypeSwitchNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java index 94a13be583..ad873666c0 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java @@ -36,7 +36,6 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDescription = "Filter incoming messages by the type of message originator entity", nodeDetails = "Checks that the entity type of the incoming message originator matches one of the values specified in the filter.

    " + "Output connections: True, False, Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeOriginatorTypeConfig") public class TbOriginatorTypeFilterNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java index 2eef991aa0..95f062e88f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeSwitchNode.java @@ -31,7 +31,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType; nodeDescription = "Route incoming messages by Message Originator Type", nodeDetails = "Routes messages to chain according to the entity type ('Device', 'Asset', etc.).

    " + "Output connections: Message originator type or Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig") public class TbOriginatorTypeSwitchNode extends TbAbstractTypeSwitchNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbAckNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbAckNode.java index 505a5b3215..b19488f0ca 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbAckNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbAckNode.java @@ -33,7 +33,6 @@ import org.thingsboard.server.common.msg.TbMsg; configClazz = EmptyNodeConfiguration.class, nodeDescription = "Acknowledges the incoming message", nodeDetails = "After acknowledgement, the message is pushed to related rule nodes. Useful if you don't care what happens to this message next.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig" ) public class TbAckNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbCheckpointNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbCheckpointNode.java index cd827c9e54..8b9f113621 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbCheckpointNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbCheckpointNode.java @@ -40,7 +40,6 @@ import static org.thingsboard.server.common.data.DataConstants.QUEUE_NAME; hasQueueName = true, nodeDescription = "transfers the message to another queue", nodeDetails = "After successful transfer incoming message is automatically acknowledged. Queue name is configurable.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig" ) public class TbCheckpointNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNode.java index 0b30d02842..a594f548e8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainInputNode.java @@ -46,7 +46,6 @@ import java.util.UUID; "then target rule chain might be resolved dynamically based on incoming message originator. " + "In this case rule chain specified in the configuration will be used as fallback rule chain.

    " + "Output connections: Any connection(s) produced by output node(s) in the target rule chain.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFlowNodeRuleChainInputConfig", relationTypes = {}, ruleChainNode = true, diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java index 2879397ace..1d887aa3a0 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/flow/TbRuleChainOutputNode.java @@ -34,7 +34,6 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDetails = "Produces output of the rule chain processing. " + "The output is forwarded to the caller rule chain, as an output of the corresponding \"input\" rule node. " + "The output 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. ", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFlowNodeRuleChainOutputConfig", outEnabled = false ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java index d6d3bb3c11..45fe4f8bc0 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/gcp/pubsub/TbPubSubNode.java @@ -52,7 +52,6 @@ import java.util.concurrent.TimeUnit; nodeDetails = "Will publish message payload to the Google Cloud Platform PubSub topic. Outbound message will contain response fields " + "(messageId in the Message Metadata from the GCP PubSub. " + "messageId field can be accessed with metadata.messageId.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodePubSubConfig", iconUrl = "data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB2aWV3Qm94PSIwIDAgMTI4IDEyOCI+Cjx0aXRsZT5DbG91ZCBQdWJTdWI8L3RpdGxlPgo8Zz4KPHBhdGggZD0iTTEyNi40Nyw1OC4xMmwtMjYuMy00NS43NEExMS41NiwxMS41NiwwLDAsMCw5MC4zMSw2LjVIMzcuN2ExMS41NSwxMS41NSwwLDAsMC05Ljg2LDUuODhMMS41Myw1OGExMS40OCwxMS40OCwwLDAsMCwwLDExLjQ0bDI2LjMsNDZhMTEuNzcsMTEuNzcsMCwwLDAsOS44Niw2LjA5SDkwLjNhMTEuNzMsMTEuNzMsMCwwLDAsOS44Ny02LjA2bDI2LjMtNDUuNzRBMTEuNzMsMTEuNzMsMCwwLDAsMTI2LjQ3LDU4LjEyWiIgc3R5bGU9ImZpbGw6ICM3MzViMmYiLz4KPHBhdGggZD0iTTg5LjIyLDQ3Ljc0LDgzLjM2LDQ5bC0xNC42LTE0LjZMNjQuMDksNDMuMSw2MS41NSw1My4ybDQuMjksNC4yOUw1Ny42LDU5LjE4LDQ2LjMsNDcuODhsLTcuNjcsNy4zOEw1Mi43Niw2OS4zN2wtMTUsMTEuOUw3OCwxMjEuNUg5MC4zYTExLjczLDExLjczLDAsMCwwLDkuODctNi4wNmwyMC43Mi0zNloiIHN0eWxlPSJvcGFjaXR5OiAwLjA3MDAwMDAwMDI5ODAyMztpc29sYXRpb246IGlzb2xhdGUiLz4KPHBhdGggZD0iTTgyLjg2LDQ3YTUuMzIsNS4zMiwwLDEsMS0xLjk1LDcuMjdBNS4zMiw1LjMyLDAsMCwxLDgyLjg2LDQ3IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNMzkuODIsNTYuMThhNS4zMiw1LjMyLDAsMSwxLDcuMjctMS45NSw1LjMyLDUuMzIsMCwwLDEtNy4yNywxLjk1IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNjkuMzIsODguODVBNS4zMiw1LjMyLDAsMSwxLDY0LDgzLjUyYTUuMzIsNS4zMiwwLDAsMSw1LjMyLDUuMzIiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxnPgo8cGF0aCBkPSJNNjQsNTIuOTRhMTEuMDYsMTEuMDYsMCwwLDEsMi40Ni4yOFYzOS4xNUg2MS41NFY1My4yMkExMS4wNiwxMS4wNiwwLDAsMSw2NCw1Mi45NFoiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik03NC41Nyw2Ny4yNmExMSwxMSwwLDAsMS0yLjQ3LDQuMjVsMTIuMTksNywyLjQ2LTQuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8cGF0aCBkPSJNNTMuNDMsNjcuMjZsLTEyLjE4LDcsMi40Niw0LjI2LDEyLjE5LTdBMTEsMTEsMCwwLDEsNTMuNDMsNjcuMjZaIiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+CjxwYXRoIGQ9Ik03Mi42LDY0QTguNiw4LjYsMCwxLDEsNjQsNTUuNCw4LjYsOC42LDAsMCwxLDcyLjYsNjQiIHN0eWxlPSJmaWxsOiAjZmZmIi8+CjxwYXRoIGQ9Ik0zOS4xLDcwLjU3YTYuNzYsNi43NiwwLDEsMS0yLjQ3LDkuMjMsNi43Niw2Ljc2LDAsMCwxLDIuNDctOS4yMyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTgyLjE0LDgyLjI3YTYuNzYsNi43NiwwLDEsMSw5LjIzLTIuNDcsNi43NSw2Ljc1LDAsMCwxLTkuMjMsMi40NyIgc3R5bGU9ImZpbGw6ICNmZmYiLz4KPHBhdGggZD0iTTcwLjc2LDM5LjE1QTYuNzYsNi43NiwwLDEsMSw2NCwzMi4zOWE2Ljc2LDYuNzYsMCwwLDEsNi43Niw2Ljc2IiBzdHlsZT0iZmlsbDogI2ZmZiIvPgo8L2c+Cjwvc3ZnPgo=" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java index b2d16434d5..a6cbb58cf5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingActionNode.java @@ -66,7 +66,6 @@ import static org.thingsboard.rule.engine.util.GpsGeofencingEvents.OUTSIDE; "If the presence monitoring strategy \"On each message\" is selected, sends messages via rule node connection type Inside or Outside every time the geofencing condition is satisfied. " + "

    " + "Output connections: Entered, Left, Inside, Outside, Success", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeGpsGeofencingConfig" ) public class TbGpsGeofencingActionNode extends AbstractGeofencingNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java index 89ca1318b7..aa95f8e523 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java @@ -60,7 +60,6 @@ import org.thingsboard.server.common.msg.TbMsg; "

    " + "Available radius units: METER, KILOMETER, FOOT, MILE, NAUTICAL_MILE;

    " + "Output connections: True, False, Failure", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbFilterNodeGpsGeofencingConfig") public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java index 865eac0aac..5a9e917427 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/kafka/TbKafkaNode.java @@ -52,7 +52,6 @@ import java.util.Properties; nodeDetails = "Will send record via Kafka producer to Kafka server. " + "Outbound message will contain response fields (offset, partition, topic)" + " from the Kafka in the Message Metadata. For example partition field can be accessed with metadata.partition.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeKafkaConfig", iconUrl = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUzOCIgaGVpZ2h0PSIyNTAwIiB2aWV3Qm94PSIwIDAgMjU2IDQxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCI+PHBhdGggZD0iTTIwMS44MTYgMjMwLjIxNmMtMTYuMTg2IDAtMzAuNjk3IDcuMTcxLTQwLjYzNCAxOC40NjFsLTI1LjQ2My0xOC4wMjZjMi43MDMtNy40NDIgNC4yNTUtMTUuNDMzIDQuMjU1LTIzLjc5NyAwLTguMjE5LTEuNDk4LTE2LjA3Ni00LjExMi0yMy40MDhsMjUuNDA2LTE3LjgzNWM5LjkzNiAxMS4yMzMgMjQuNDA5IDE4LjM2NSA0MC41NDggMTguMzY1IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI5Ljg3OS0yNC4zMDktNTQuMTg0LTU0LjE4NC01NC4xODQtMjkuODc1IDAtNTQuMTg0IDI0LjMwNS01NC4xODQgNTQuMTg0IDAgNS4zNDguODA4IDEwLjUwNSAyLjI1OCAxNS4zODlsLTI1LjQyMyAxNy44NDRjLTEwLjYyLTEzLjE3NS0yNS45MTEtMjIuMzc0LTQzLjMzMy0yNS4xODJ2LTMwLjY0YzI0LjU0NC01LjE1NSA0My4wMzctMjYuOTYyIDQzLjAzNy01My4wMTlDMTI0LjE3MSAyNC4zMDUgOTkuODYyIDAgNjkuOTg3IDAgNDAuMTEyIDAgMTUuODAzIDI0LjMwNSAxNS44MDMgNTQuMTg0YzAgMjUuNzA4IDE4LjAxNCA0Ny4yNDYgNDIuMDY3IDUyLjc2OXYzMS4wMzhDMjUuMDQ0IDE0My43NTMgMCAxNzIuNDAxIDAgMjA2Ljg1NGMwIDM0LjYyMSAyNS4yOTIgNjMuMzc0IDU4LjM1NSA2OC45NHYzMi43NzRjLTI0LjI5OSA1LjM0MS00Mi41NTIgMjcuMDExLTQyLjU1MiA1Mi44OTQgMCAyOS44NzkgMjQuMzA5IDU0LjE4NCA1NC4xODQgNTQuMTg0IDI5Ljg3NSAwIDU0LjE4NC0yNC4zMDUgNTQuMTg0LTU0LjE4NCAwLTI1Ljg4My0xOC4yNTMtNDcuNTUzLTQyLjU1Mi01Mi44OTR2LTMyLjc3NWE2OS45NjUgNjkuOTY1IDAgMCAwIDQyLjYtMjQuNzc2bDI1LjYzMyAxOC4xNDNjLTEuNDIzIDQuODQtMi4yMiA5Ljk0Ni0yLjIyIDE1LjI0IDAgMjkuODc5IDI0LjMwOSA1NC4xODQgNTQuMTg0IDU0LjE4NCAyOS44NzUgMCA1NC4xODQtMjQuMzA1IDU0LjE4NC01NC4xODQgMC0yOS44NzktMjQuMzA5LTU0LjE4NC01NC4xODQtNTQuMTg0em0wLTEyNi42OTVjMTQuNDg3IDAgMjYuMjcgMTEuNzg4IDI2LjI3IDI2LjI3MXMtMTEuNzgzIDI2LjI3LTI2LjI3IDI2LjI3LTI2LjI3LTExLjc4Ny0yNi4yNy0yNi4yN2MwLTE0LjQ4MyAxMS43ODMtMjYuMjcxIDI2LjI3LTI2LjI3MXptLTE1OC4xLTQ5LjMzN2MwLTE0LjQ4MyAxMS43ODQtMjYuMjcgMjYuMjcxLTI2LjI3czI2LjI3IDExLjc4NyAyNi4yNyAyNi4yN2MwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3em01Mi41NDEgMzA3LjI3OGMwIDE0LjQ4My0xMS43ODMgMjYuMjctMjYuMjcgMjYuMjdzLTI2LjI3MS0xMS43ODctMjYuMjcxLTI2LjI3YzAtMTQuNDgzIDExLjc4NC0yNi4yNyAyNi4yNzEtMjYuMjdzMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3em0tMjYuMjcyLTExNy45N2MtMjAuMjA1IDAtMzYuNjQyLTE2LjQzNC0zNi42NDItMzYuNjM4IDAtMjAuMjA1IDE2LjQzNy0zNi42NDIgMzYuNjQyLTM2LjY0MiAyMC4yMDQgMCAzNi42NDEgMTYuNDM3IDM2LjY0MSAzNi42NDIgMCAyMC4yMDQtMTYuNDM3IDM2LjYzOC0zNi42NDEgMzYuNjM4em0xMzEuODMxIDY3LjE3OWMtMTQuNDg3IDAtMjYuMjctMTEuNzg4LTI2LjI3LTI2LjI3MXMxMS43ODMtMjYuMjcgMjYuMjctMjYuMjcgMjYuMjcgMTEuNzg3IDI2LjI3IDI2LjI3YzAgMTQuNDgzLTExLjc4MyAyNi4yNzEtMjYuMjcgMjYuMjcxeiIvPjwvc3ZnPg==" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java index 864528b3a4..dd26a64993 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbMsgToEmailNode.java @@ -42,7 +42,6 @@ import java.util.Map; nodeDescription = "Transforms message to email message", nodeDetails = "Transforms message to email message. If transformation completed successfully output message type will be set to SEND_EMAIL.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbTransformationNodeToEmailConfig", icon = "email" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java index 7be40fc829..27fdce68d9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mail/TbSendEmailNode.java @@ -44,7 +44,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; nodeDetails = "Expects messages with SEND_EMAIL type. Node works only with messages that " + " where created using to Email transformation Node, please connect this Node " + "with to Email Node using Successful chain.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeSendEmailConfig", icon = "send" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/math/TbMathNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/math/TbMathNode.java index d72a23708e..27afa06f90 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/math/TbMathNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/math/TbMathNode.java @@ -76,7 +76,6 @@ import static org.thingsboard.rule.engine.math.TbMathArgumentType.CONSTANT; "

    " + "The execution is synchronized in scope of message originator (e.g. device) and server node. " + "If you have rule nodes in different rule chains, they will process messages from the same originator synchronously in the scope of the server node.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeMathFunctionConfig", icon = "calculate" diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNode.java index 75d0e774a2..48c3ba4778 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/CalculateDeltaNode.java @@ -53,7 +53,6 @@ import java.util.Map; "and current value for this key from the incoming message", nodeDetails = "Useful for metering use cases, when you need to calculate consumption based on pulse counter reading.

    " + "Output connections: Success, Other or Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeCalculateDeltaConfig") public class CalculateDeltaNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbFetchDeviceCredentialsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbFetchDeviceCredentialsNode.java index 3362d60fac..6d11419e72 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbFetchDeviceCredentialsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbFetchDeviceCredentialsNode.java @@ -45,7 +45,6 @@ import java.util.concurrent.ExecutionException; "Useful when you need to fetch device credentials and use them for further message processing. " + "For example, use device credentials to interact with external systems.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeFetchDeviceCredentialsConfig") public class TbFetchDeviceCredentialsNode extends TbAbstractNodeWithFetchTo { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java index f618befb97..586b5077e2 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetAttributesNode.java @@ -43,7 +43,6 @@ import org.thingsboard.server.common.msg.TbMsg; "that are not included in the incoming message to use them for further message processing. " + "For example to filter messages based on the threshold value stored in the attributes.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeOriginatorAttributesConfig") public class TbGetAttributesNode extends TbAbstractGetAttributesNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java index ea48f3a2c4..37a9d052e6 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerAttributeNode.java @@ -41,7 +41,6 @@ import org.thingsboard.server.common.data.util.TbPair; "that is stored as customer attributes or telemetry data and used for dynamic message filtering, transformation, " + "or actions such as alarm creation if the threshold is exceeded.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeCustomerAttributesConfig") public class TbGetCustomerAttributeNode extends TbAbstractGetEntityDataNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java index eb6eeb1e06..33cc5812e9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetCustomerDetailsNode.java @@ -50,7 +50,6 @@ import java.util.NoSuchElementException; nodeDetails = "Useful in multi-customer solutions where we need dynamically use customer contact information " + "such as email, phone, address, etc., for notifications via email, SMS, and other notification providers.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeEntityDetailsConfig") public class TbGetCustomerDetailsNode extends TbAbstractGetEntityDetailsNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java index 0e257ac3be..1dac58224c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetDeviceAttrNode.java @@ -42,7 +42,6 @@ import org.thingsboard.server.common.msg.TbMsg; "Useful when you need to retrieve attributes and/or latest telemetry values from device that has a relation " + "to the message originator and use them for further message processing.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeDeviceAttributesConfig") public class TbGetDeviceAttrNode extends TbAbstractGetAttributesNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java index 391289cc5d..3807097349 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetOriginatorFieldsNode.java @@ -43,7 +43,6 @@ import java.util.concurrent.ExecutionException; nodeDetails = "Fetches fields values specified in the mapping. If specified field is not part of originator fields it will be ignored. " + "Useful when you need to retrieve originator fields and use them for further message processing.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeOriginatorFieldsConfig") public class TbGetOriginatorFieldsNode extends TbAbstractGetMappedDataNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java index d107de25c6..639f234f7e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetRelatedAttributeNode.java @@ -42,7 +42,6 @@ import java.util.Arrays; "If multiple related entities are found, only first entity is used for message enrichment, other entities are discarded. " + "Useful when you need to retrieve data from an entity that has a relation to the message originator and use them for further message processing.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeRelatedAttributesConfig") public class TbGetRelatedAttributeNode extends TbAbstractGetEntityDataNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index 8e6e64bb17..b5d9361d50 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -58,7 +58,6 @@ import java.util.stream.Collectors; "instead of fetching just the latest telemetry or if you need to get the closest telemetry to the fetch interval start or end. " + "Also, this node can be used for telemetry aggregation within configured fetch interval.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase") public class TbGetTelemetryNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java index c1f8e95896..5738eb801b 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantAttributeNode.java @@ -39,7 +39,6 @@ import org.thingsboard.server.common.data.util.TbPair; nodeDetails = "Useful when you need to retrieve some common configuration or threshold set " + "that is stored as tenant attributes or telemetry data and use it for further message processing.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeTenantAttributesConfig") public class TbGetTenantAttributeNode extends TbAbstractGetEntityDataNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java index c18cb1f942..ef54aae34e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTenantDetailsNode.java @@ -39,7 +39,6 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDetails = "Useful when we need to retrieve contact information from your tenant " + "such as email, phone, address, etc., for notifications via email, SMS, and other notification providers.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeEntityDetailsConfig") public class TbGetTenantDetailsNode extends TbAbstractGetEntityDetailsNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java index 56bfe038a8..9576384ab4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/TbMqttNode.java @@ -57,7 +57,6 @@ import java.util.concurrent.TimeoutException; clusteringMode = ComponentClusteringMode.USER_PREFERENCE, nodeDescription = "Publish messages to the MQTT broker", nodeDetails = "Will publish message payload to the MQTT broker with QoS AT_LEAST_ONCE.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeMqttConfig", icon = "call_split" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java index cbf431d63a..836fb215d9 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/mqtt/azure/TbAzureIotHubNode.java @@ -41,7 +41,6 @@ import org.thingsboard.server.common.data.plugin.ComponentType; clusteringMode = ComponentClusteringMode.SINGLETON, nodeDescription = "Publish messages to the Azure IoT Hub", nodeDetails = "Will publish message payload to the Azure IoT Hub with QoS AT_LEAST_ONCE.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeAzureIotHubConfig" ) public class TbAzureIotHubNode extends TbMqttNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java index 8ae3da7bad..4777a411dc 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbNotificationNode.java @@ -41,7 +41,6 @@ import java.util.concurrent.ExecutionException; configClazz = TbNotificationNodeConfiguration.class, nodeDescription = "Sends notification to targets using the template", nodeDetails = "Will send notification to the specified targets using the template", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeNotificationConfig", icon = "notifications" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbSlackNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbSlackNode.java index 78e0b1e46c..a9c62c8d80 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbSlackNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/notification/TbSlackNode.java @@ -33,7 +33,6 @@ import java.util.concurrent.ExecutionException; configClazz = TbSlackNodeConfiguration.class, nodeDescription = "Send message via Slack", nodeDetails = "Sends message to a Slack channel or user", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeSlackConfig", iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTYsMTVBMiwyIDAgMCwxIDQsMTdBMiwyIDAgMCwxIDIsMTVBMiwyIDAgMCwxIDQsMTNINlYxNU03LDE1QTIsMiAwIDAsMSA5LDEzQTIsMiAwIDAsMSAxMSwxNVYyMEEyLDIgMCAwLDEgOSwyMkEyLDIgMCAwLDEgNywyMFYxNU05LDdBMiwyIDAgMCwxIDcsNUEyLDIgMCAwLDEgOSwzQTIsMiAwIDAsMSAxMSw1VjdIOU05LDhBMiwyIDAgMCwxIDExLDEwQTIsMiAwIDAsMSA5LDEySDRBMiwyIDAgMCwxIDIsMTBBMiwyIDAgMCwxIDQsOEg5TTE3LDEwQTIsMiAwIDAsMSAxOSw4QTIsMiAwIDAsMSAyMSwxMEEyLDIgMCAwLDEgMTksMTJIMTdWMTBNMTYsMTBBMiwyIDAgMCwxIDE0LDEyQTIsMiAwIDAsMSAxMiwxMFY1QTIsMiAwIDAsMSAxNCwzQTIsMiAwIDAsMSAxNiw1VjEwTTE0LDE4QTIsMiAwIDAsMSAxNiwyMEEyLDIgMCAwLDEgMTQsMjJBMiwyIDAgMCwxIDEyLDIwVjE4SDE0TTE0LDE3QTIsMiAwIDAsMSAxMiwxNUEyLDIgMCAwLDEgMTQsMTNIMTlBMiwyIDAgMCwxIDIxLDE1QTIsMiAwIDAsMSAxOSwxN0gxNFoiIC8+PC9zdmc+" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java index c57a9a1433..9df674cf88 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java @@ -59,7 +59,6 @@ import java.util.concurrent.TimeUnit; nodeDescription = "Process device messages based on device profile settings", nodeDetails = "Create and clear alarms based on alarm rules defined in device profile. The output relation type is either " + "'Alarm Created', 'Alarm Updated', 'Alarm Severity Updated' and 'Alarm Cleared' or simply 'Success' if no alarms were affected.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbDeviceProfileConfig" ) public class TbDeviceProfileNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java index 8b724ae86e..ebd2a57e59 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rabbitmq/TbRabbitMqNode.java @@ -45,7 +45,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; configClazz = TbRabbitMqNodeConfiguration.class, nodeDescription = "Publish messages to the RabbitMQ", nodeDetails = "Will publish message payload to RabbitMQ queue.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeRabbitMqConfig", iconUrl = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZlcnNpb249IjEuMSIgeT0iMHB4IiB4PSIwcHgiIHZpZXdCb3g9IjAgMCAxMDAwIDEwMDAiPjxwYXRoIHN0cm9rZS13aWR0aD0iLjg0OTU2IiBkPSJtODYwLjQ3IDQxNi4zMmgtMjYyLjAxYy0xMi45MTMgMC0yMy42MTgtMTAuNzA0LTIzLjYxOC0yMy42MTh2LTI3Mi43MWMwLTIwLjMwNS0xNi4yMjctMzYuMjc2LTM2LjI3Ni0zNi4yNzZoLTkzLjc5MmMtMjAuMzA1IDAtMzYuMjc2IDE2LjIyNy0zNi4yNzYgMzYuMjc2djI3MC44NGMtMC4yNTQ4NyAxNC4xMDMtMTEuNDY5IDI1LjU3Mi0yNS43NDIgMjUuNTcybC04NS42MzYgMC42Nzk2NWMtMTQuMTAzIDAtMjUuNTcyLTExLjQ2OS0yNS41NzItMjUuNTcybDAuNjc5NjUtMjcxLjUyYzAtMjAuMzA1LTE2LjIyNy0zNi4yNzYtMzYuMjc2LTM2LjI3NmgtOTMuNTM3Yy0yMC4zMDUgMC0zNi4yNzYgMTYuMjI3LTM2LjI3NiAzNi4yNzZ2NzYzLjg0YzAgMTguMDk2IDE0Ljc4MiAzMi40NTMgMzIuNDUzIDMyLjQ1M2g3MjIuODFjMTguMDk2IDAgMzIuNDUzLTE0Ljc4MiAzMi40NTMtMzIuNDUzdi00MzUuMzFjLTEuMTg5NC0xOC4xODEtMTUuMjkyLTMyLjE5OC0zMy4zODgtMzIuMTk4em0tMTIyLjY4IDI4Ny4wN2MwIDIzLjYxOC0xOC44NiA0Mi40NzgtNDIuNDc4IDQyLjQ3OGgtNzMuOTk3Yy0yMy42MTggMC00Mi40NzgtMTguODYtNDIuNDc4LTQyLjQ3OHYtNzQuMjUyYzAtMjMuNjE4IDE4Ljg2LTQyLjQ3OCA0Mi40NzgtNDIuNDc4aDczLjk5N2MyMy42MTggMCA0Mi40NzggMTguODYgNDIuNDc4IDQyLjQ3OHoiLz48L3N2Zz4=" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java index 0e65905dfe..d25e1d647c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbRestApiCallNode.java @@ -45,7 +45,6 @@ import java.util.List; "For example statusCode field can be accessed with metadata.statusCode." + "
    Note- if you use system proxy properties, the next system proxy properties should be added: \"http.proxyHost\" and \"http.proxyPort\" or \"https.proxyHost\" and \"https.proxyPort\" or \"socksProxyHost\" and \"socksProxyPort\"," + "and if your proxy with auth, the next ones should be added: \"tb.proxy.user\" and \"tb.proxy.password\" to the thingsboard.conf file.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeRestApiCallConfig", iconUrl = "data:image/svg+xml;base64,PHN2ZyBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MTIgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbDpzcGFjZT0icHJlc2VydmUiIHZpZXdCb3g9IjAgMCA1MTIgNTEyIiB2ZXJzaW9uPSIxLjEiIHk9IjBweCIgeD0iMHB4Ij48ZyB0cmFuc2Zvcm09Im1hdHJpeCguOTQ5NzUgMCAwIC45NDk3NSAxNy4xMiAyNi40OTIpIj48cGF0aCBkPSJtMTY5LjExIDEwOC41NGMtOS45MDY2IDAuMDczNC0xOS4wMTQgNi41NzI0LTIyLjAxNCAxNi40NjlsLTY5Ljk5MyAyMzEuMDhjLTMuNjkwNCAxMi4xODEgMy4yODkyIDI1LjIyIDE1LjQ2OSAyOC45MSAyLjIyNTkgMC42NzQ4MSA0LjQ5NjkgMSA2LjcyODUgMSA5Ljk3MjEgMCAxOS4xNjUtNi41MTUzIDIyLjE4Mi0xNi40NjdhNi41MjI0IDYuNTIyNCAwIDAgMCAwLjAwMiAtMC4wMDJsNjkuOTktMjMxLjA3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMCAtMC4wMDJjMy42ODU1LTEyLjE4MS0zLjI4Ny0yNS4yMjUtMTUuNDcxLTI4LjkxMi0yLjI4MjUtMC42OTE0NS00LjYxMTYtMS4wMTY5LTYuODk4NC0xem04NC45ODggMGMtOS45MDQ4IDAuMDczNC0xOS4wMTggNi41Njc1LTIyLjAxOCAxNi40NjlsLTY5Ljk4NiAyMzEuMDhjLTMuNjg5OCAxMi4xNzkgMy4yODUzIDI1LjIxNyAxNS40NjUgMjguOTA4IDIuMjI5NyAwLjY3NjQ3IDQuNTAwOCAxLjAwMiA2LjczMjQgMS4wMDIgOS45NzIxIDAgMTkuMTY1LTYuNTE1MyAyMi4xODItMTYuNDY3YTYuNTIyNCA2LjUyMjQgMCAwIDAgMC4wMDIgLTAuMDAybDY5Ljk4OC0yMzEuMDdjMy42OTA4LTEyLjE4MS0zLjI4NTItMjUuMjIzLTE1LjQ2Ny0yOC45MTItMi4yODE0LTAuNjkyMzEtNC42MTA4LTEuMDE4OS02Ljg5ODQtMS4wMDJ6bS0yMTcuMjkgNDIuMjNjLTEyLjcyOS0wLjAwMDg3LTIzLjE4OCAxMC40NTYtMjMuMTg4IDIzLjE4NiAwLjAwMSAxMi43MjggMTAuNDU5IDIzLjE4NiAyMy4xODggMjMuMTg2IDEyLjcyNy0wLjAwMSAyMy4xODMtMTAuNDU5IDIzLjE4NC0yMy4xODYgMC4wMDA4NzYtMTIuNzI4LTEwLjQ1Ni0yMy4xODUtMjMuMTg0LTIzLjE4NnptMCAxNDYuNjRjLTEyLjcyNy0wLjAwMDg3LTIzLjE4NiAxMC40NTUtMjMuMTg4IDIzLjE4NC0wLjAwMDg3MyAxMi43MjkgMTAuNDU4IDIzLjE4OCAyMy4xODggMjMuMTg4IDEyLjcyOC0wLjAwMSAyMy4xODQtMTAuNDYgMjMuMTg0LTIzLjE4OC0wLjAwMS0xMi43MjYtMTAuNDU3LTIzLjE4My0yMy4xODQtMjMuMTg0em0yNzAuNzkgNDIuMjExYy0xMi43MjcgMC0yMy4xODQgMTAuNDU3LTIzLjE4NCAyMy4xODRzMTAuNDU1IDIzLjE4OCAyMy4xODQgMjMuMTg4aDE1NC45OGMxMi43MjkgMCAyMy4xODYtMTAuNDYgMjMuMTg2LTIzLjE4OCAwLjAwMS0xMi43MjgtMTAuNDU4LTIzLjE4NC0yMy4xODYtMjMuMTg0eiIgdHJhbnNmb3JtPSJtYXRyaXgoMS4wMzc2IDAgMCAxLjAzNzYgLTcuNTY3NiAtMTQuOTI1KSIgc3Ryb2tlLXdpZHRoPSIxLjI2OTMiLz48L2c+PC9zdmc+" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbSendRestApiCallReplyNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbSendRestApiCallReplyNode.java index 84441fb213..0c6e449576 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbSendRestApiCallReplyNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rest/TbSendRestApiCallReplyNode.java @@ -35,7 +35,6 @@ import java.util.UUID; configClazz = TbSendRestApiCallReplyNodeConfiguration.class, nodeDescription = "Sends reply to REST API call to rule engine", nodeDetails = "Expects messages with any message type. Forwards incoming message as a reply to REST API call sent to rule engine.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeSendRestApiCallReplyConfig", icon = "call_merge" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java index c343b242bf..1f071b590e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCReplyNode.java @@ -48,7 +48,6 @@ import java.util.UUID; configClazz = TbSendRpcReplyNodeConfiguration.class, nodeDescription = "Sends reply to RPC call from device", nodeDetails = "Expects messages with any message type. Will forward message body to the device.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeRpcReplyConfig", icon = "call_merge" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java index 81863f9410..76d6649734 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/rpc/TbSendRPCRequestNode.java @@ -49,7 +49,6 @@ import java.util.concurrent.TimeUnit; nodeDescription = "Sends RPC call to device", nodeDetails = "Expects messages with \"method\" and \"params\". Will forward response from device to next nodes." + "If the RPC call request is originated by REST API call from user, will forward the response to user immediately.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeRpcRequestConfig", icon = "call_made" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNode.java index 0024936b89..3fbd074a14 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNode.java @@ -35,7 +35,6 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback; configClazz = TbSendSmsNodeConfiguration.class, nodeDescription = "Sends SMS message via SMS provider.", nodeDetails = "Will send SMS message by populating target phone numbers and sms message fields using values derived from message metadata.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbExternalNodeSendSmsConfig", icon = "sms" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java index e83a125265..c57c62e2ae 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgAttributesNode.java @@ -62,7 +62,6 @@ import static org.thingsboard.server.common.data.msg.TbMsgType.POST_ATTRIBUTES_R "Additionally if checkbox Send attributes updated notification is set to true, rule node will put the \"Attributes Updated\" " + "event for SHARED_SCOPE and SERVER_SCOPE attributes updates to the corresponding rule engine queue." + "Performance checkbox 'Save attributes only if the value changes' will skip attributes overwrites for values with no changes (avoid concurrent writes because this check is not transactional; will not update 'Last updated time' for skipped attributes).", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeAttributesConfig", icon = "file_upload" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNode.java index f1f1a29f3c..a89a4f37d8 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgDeleteAttributesNode.java @@ -45,7 +45,6 @@ import static org.thingsboard.server.common.data.DataConstants.SCOPE; " a key selected in the configuration, it will be ignored. If delete operation is completed successfully, " + " rule node will send the \"Attributes Deleted\" event to the root chain of the message originator and " + " send the incoming message via Success chain, otherwise, Failure chain is used.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeDeleteAttributesConfig", icon = "remove_circle" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java index 27f45feb47..b0bdb1de69 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java @@ -58,7 +58,6 @@ import static org.thingsboard.server.common.data.msg.TbMsgType.POST_TELEMETRY_RE "However, the timestamp of the messages originated by multiple devices/servers may be unsynchronized long before they are pushed to the queue. " + "The DB layer has certain optimizations to ignore the updates of the \"attributes\" and \"latest values\" tables if the new record has a timestamp that is older than the previous record. " + "So, to make sure that all the messages will be processed correctly, one should enable this parameter for sequential message processing scenarios.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbActionNodeTimeseriesConfig", icon = "file_upload" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java index 543767cfeb..50d668b1d4 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationBeginNode.java @@ -34,7 +34,6 @@ import org.thingsboard.server.common.msg.TbMsg; nodeDetails = "This node should be used together with \"synchronization end\" node. \n This node will put messages into queue based on message originator id. \n" + "Subsequent messages will not be processed until the previous message processing is completed or timeout event occurs.\n" + "Size of the queue per originator and timeout values are configurable on a system level", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig") @Deprecated public class TbSynchronizationBeginNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java index 6f1344acf3..9407414dcb 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transaction/TbSynchronizationEndNode.java @@ -32,7 +32,6 @@ import org.thingsboard.server.common.msg.TbMsg; configClazz = EmptyNodeConfiguration.class, nodeDescription = "This Node is now deprecated. Use \"Checkpoint\" instead.", nodeDetails = "", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = ("tbNodeEmptyConfig") ) @Deprecated diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java index d590bbbb75..e45f1dd8b2 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbChangeOriginatorNode.java @@ -54,7 +54,6 @@ import static org.thingsboard.rule.engine.transform.OriginatorSource.RELATED; "
  • Entity by name pattern - specify entity type and name pattern of new originator. Following entity types are supported: " + "'Device', 'Asset', 'Entity View', 'Edge' or 'User'.
  • " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbTransformationNodeChangeOriginatorConfig", icon = "find_replace" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbCopyKeysNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbCopyKeysNode.java index 1417618a54..aadc3a3851 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbCopyKeysNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbCopyKeysNode.java @@ -46,7 +46,6 @@ import java.util.stream.Collectors; nodeDetails = "Copies key-value pairs from the message to message metadata, or vice-versa, according to the configured direction and keys. " + "Regular expressions can be used to define which keys-value pairs to copy. Any configured key not found in the source will be ignored.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbTransformationNodeCopyKeysConfig", icon = "content_copy" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbDeleteKeysNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbDeleteKeysNode.java index cf31381af2..412b523786 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbDeleteKeysNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbDeleteKeysNode.java @@ -46,7 +46,6 @@ import java.util.stream.Collectors; nodeDetails = "Deletes key-value pairs from the message or message metadata according to the configured " + "keys and/or regular expressions.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbTransformationNodeDeleteKeysConfig", icon = "remove_circle" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbJsonPathNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbJsonPathNode.java index 043e914c2c..af9121e8a1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbJsonPathNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbJsonPathNode.java @@ -40,7 +40,6 @@ import java.util.concurrent.ExecutionException; nodeDescription = "Transforms incoming message body using JSONPath expression.", nodeDetails = "JSONPath expression specifies a path to an element or a set of elements in a JSON structure.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, icon = "functions", configDirective = "tbTransformationNodeJsonPathConfig" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbRenameKeysNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbRenameKeysNode.java index 490504c42b..904e624c75 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbRenameKeysNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbRenameKeysNode.java @@ -43,7 +43,6 @@ import java.util.concurrent.ExecutionException; nodeDetails = "Renames keys in the message or message metadata according to the provided mapping. " + "If key to rename doesn't exist in the specified source (message or message metadata) it will be ignored.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbTransformationNodeRenameKeysConfig", icon = "find_replace" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNode.java index 92a3dd8d09..588d073cac 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbSplitArrayMsgNode.java @@ -43,7 +43,6 @@ import java.util.concurrent.ExecutionException; nodeDetails = "Splits an array message into individual elements, with each element sent as a separate message. " + "All outbound messages will have the same type and metadata as the original array message.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, icon = "content_copy", configDirective = "tbNodeEmptyConfig" ) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java index 3227c0c52c..01c6bd36c2 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/transform/TbTransformMsgNode.java @@ -41,7 +41,6 @@ import java.util.List; "{ msg: new payload,
       metadata: new metadata,
       msgType: new msgType }

    " + "All fields in resulting object are optional and will be taken from original message if not specified.

    " + "Output connections: Success, Failure.", - uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbTransformationNodeScriptConfig" ) public class TbTransformMsgNode extends TbAbstractTransformNode { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.html new file mode 100644 index 0000000000..486764f936 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.html @@ -0,0 +1,35 @@ + +
    +
    + + tb.rulenode.customer-name-pattern + + + {{ 'tb.rulenode.customer-name-pattern-required' | translate }} + + tb.rulenode.customer-name-pattern-hint + +
    + + {{ 'tb.rulenode.create-customer-if-not-exists' | translate }} + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.ts new file mode 100644 index 0000000000..924cb448e3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.ts @@ -0,0 +1,49 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-assign-to-customer-config', + templateUrl: './assign-customer-config.component.html', + styleUrls: [] +}) +export class AssignCustomerConfigComponent extends RuleNodeConfigurationComponent { + + assignCustomerConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.assignCustomerConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.assignCustomerConfigForm = this.fb.group({ + customerNamePattern: [configuration ? configuration.customerNamePattern : null, [Validators.required, Validators.pattern(/.*\S.*/)]], + createCustomerIfNotExists: [configuration ? configuration.createCustomerIfNotExists : false, []] + }); + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + configuration.customerNamePattern = configuration.customerNamePattern.trim(); + return configuration; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.html new file mode 100644 index 0000000000..80633ca0d3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.html @@ -0,0 +1,79 @@ + +
    +
    + + +
    + + {{ 'tb.rulenode.attributes-scope' | translate }} + + + {{ telemetryTypeTranslationsMap.get(scope) | translate }} + + + + + {{ 'tb.rulenode.attributes-scope-value' | translate }} + + + +
    +
    + +
    + + + tb.rulenode.advanced-settings + +
    + + {{ 'tb.rulenode.update-attributes-only-on-value-change' | translate }} + +
    +
    + + {{ 'tb.rulenode.send-attributes-updated-notification' | translate }} + +
    +
    + + {{ 'tb.rulenode.notify-device' | translate }} + +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts new file mode 100644 index 0000000000..a60a4ae40e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts @@ -0,0 +1,62 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { AttributeScope, telemetryTypeTranslations } from '@app/shared/models/telemetry/telemetry.models'; + +@Component({ + selector: 'tb-action-node-attributes-config', + templateUrl: './attributes-config.component.html', + styleUrls: [] +}) +export class AttributesConfigComponent extends RuleNodeConfigurationComponent { + + attributeScopeMap = AttributeScope; + attributeScopes = Object.keys(AttributeScope); + telemetryTypeTranslationsMap = telemetryTypeTranslations; + + attributesConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.attributesConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.attributesConfigForm = this.fb.group({ + scope: [configuration ? configuration.scope : null, [Validators.required]], + notifyDevice: [configuration ? configuration.notifyDevice : true, []], + sendAttributesUpdatedNotification: [configuration ? configuration.sendAttributesUpdatedNotification : false, []], + updateAttributesOnlyOnValueChange: [configuration ? configuration.updateAttributesOnlyOnValueChange : false, []] + }); + + this.attributesConfigForm.get('scope').valueChanges.subscribe((value) => { + if (value !== AttributeScope.SHARED_SCOPE) { + this.attributesConfigForm.get('notifyDevice').patchValue(false, {emitEvent: false}); + } + if (value === AttributeScope.CLIENT_SCOPE) { + this.attributesConfigForm.get('sendAttributesUpdatedNotification').patchValue(false, {emitEvent: false}); + } + this.attributesConfigForm.get('updateAttributesOnlyOnValueChange').patchValue(false, {emitEvent: false}); + }); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.html new file mode 100644 index 0000000000..1a348734a8 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.html @@ -0,0 +1,67 @@ + +
    + + + + + + + +
    + +
    + + tb.rulenode.alarm-type + + + {{ 'tb.rulenode.alarm-type-required' | translate }} + + tb.rulenode.general-pattern-hint + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts new file mode 100644 index 0000000000..f132d737eb --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts @@ -0,0 +1,127 @@ +/// +/// 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, EventEmitter, ViewChild } from '@angular/core'; +import { AppState, getCurrentAuthState, NodeScriptTestService } from '@core/public-api'; +import { Store } from '@ngrx/store'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { + RuleNodeConfiguration, + RuleNodeConfigurationComponent, + ScriptLanguage +} from '@app/shared/models/rule-node.models'; +import type { JsFuncComponent } from '@app/shared/components/js-func.component'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; + +@Component({ + selector: 'tb-action-node-clear-alarm-config', + templateUrl: './clear-alarm-config.component.html', + styleUrls: [] +}) +export class ClearAlarmConfigComponent extends RuleNodeConfigurationComponent { + + @ViewChild('jsFuncComponent', {static: false}) jsFuncComponent: JsFuncComponent; + @ViewChild('tbelFuncComponent', {static: false}) tbelFuncComponent: JsFuncComponent; + + clearAlarmConfigForm: UntypedFormGroup; + + tbelEnabled = getCurrentAuthState(this.store).tbelEnabled; + + scriptLanguage = ScriptLanguage; + + changeScript: EventEmitter = new EventEmitter(); + + readonly hasScript = true; + + readonly testScriptLabel = 'tb.rulenode.test-details-function'; + + constructor(protected store: Store, + private fb: UntypedFormBuilder, + private nodeScriptTestService: NodeScriptTestService, + private translate: TranslateService) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.clearAlarmConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.clearAlarmConfigForm = this.fb.group({ + scriptLang: [configuration ? configuration.scriptLang : ScriptLanguage.JS, [Validators.required]], + alarmDetailsBuildJs: [configuration ? configuration.alarmDetailsBuildJs : null, []], + alarmDetailsBuildTbel: [configuration ? configuration.alarmDetailsBuildTbel : null, []], + alarmType: [configuration ? configuration.alarmType : null, [Validators.required]] + }); + } + + protected validatorTriggers(): string[] { + return ['scriptLang']; + } + + protected updateValidators(emitEvent: boolean) { + let scriptLang: ScriptLanguage = this.clearAlarmConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.TBEL && !this.tbelEnabled) { + scriptLang = ScriptLanguage.JS; + this.clearAlarmConfigForm.get('scriptLang').patchValue(scriptLang, {emitEvent: false}); + setTimeout(() => {this.clearAlarmConfigForm.updateValueAndValidity({emitEvent: true});}); + } + this.clearAlarmConfigForm.get('alarmDetailsBuildJs').setValidators(scriptLang === ScriptLanguage.JS ? [Validators.required] : []); + this.clearAlarmConfigForm.get('alarmDetailsBuildJs').updateValueAndValidity({emitEvent}); + this.clearAlarmConfigForm.get('alarmDetailsBuildTbel').setValidators(scriptLang === ScriptLanguage.TBEL ? [Validators.required] : []); + this.clearAlarmConfigForm.get('alarmDetailsBuildTbel').updateValueAndValidity({emitEvent}); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (configuration) { + if (!configuration.scriptLang) { + configuration.scriptLang = ScriptLanguage.JS; + } + } + return configuration; + } + + testScript(debugEventBody?: DebugRuleNodeEventBody) { + const scriptLang: ScriptLanguage = this.clearAlarmConfigForm.get('scriptLang').value; + const scriptField = scriptLang === ScriptLanguage.JS ? 'alarmDetailsBuildJs' : 'alarmDetailsBuildTbel'; + const helpId = scriptLang === ScriptLanguage.JS ? 'rulenode/clear_alarm_node_script_fn' : 'rulenode/tbel/clear_alarm_node_script_fn'; + const script: string = this.clearAlarmConfigForm.get(scriptField).value; + this.nodeScriptTestService.testNodeScript( + script, + 'json', + this.translate.instant('tb.rulenode.details'), + 'Details', + ['msg', 'metadata', 'msgType'], + this.ruleNodeId, + helpId, + scriptLang, + debugEventBody + ).subscribe((theScript) => { + if (theScript) { + this.clearAlarmConfigForm.get(scriptField).setValue(theScript); + this.changeScript.emit(); + } + }); + } + + protected onValidate() { + const scriptLang: ScriptLanguage = this.clearAlarmConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.JS) { + this.jsFuncComponent.validateOnSubmit(); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.html new file mode 100644 index 0000000000..9b1efd0f1a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.html @@ -0,0 +1,128 @@ + +
    + + {{ 'tb.rulenode.use-message-alarm-data' | translate }} + + + {{ 'tb.rulenode.overwrite-alarm-details' | translate }} + +
    + + + + + + + +
    + +
    +
    +
    + + tb.rulenode.alarm-type + + + {{ 'tb.rulenode.alarm-type-required' | translate }} + + tb.rulenode.general-pattern-hint + + + {{ 'tb.rulenode.use-alarm-severity-pattern' | translate }} + + + tb.rulenode.alarm-severity + + + {{ alarmSeverityTranslationMap.get(severity) | translate }} + + + + {{ 'tb.rulenode.alarm-severity-required' | translate }} + + + + tb.rulenode.alarm-severity-pattern + + + {{ 'tb.rulenode.alarm-severity-required' | translate }} + + + + + {{ 'tb.rulenode.propagate' | translate }} + +
    + + tb.rulenode.relation-types-list + + + {{key}} + close + + + + tb.rulenode.relation-types-list-hint + +
    + + {{ 'tb.rulenode.propagate-to-owner' | translate }} + + + {{ 'tb.rulenode.propagate-to-tenant' | translate }} + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts new file mode 100644 index 0000000000..b5639f15ac --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts @@ -0,0 +1,199 @@ +/// +/// 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, EventEmitter, ViewChild } from '@angular/core'; +import { AppState, getCurrentAuthState, NodeScriptTestService } from '@core/public-api'; +import { Store } from '@ngrx/store'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; +import { MatChipInputEvent } from '@angular/material/chips'; +import { + RuleNodeConfiguration, + RuleNodeConfigurationComponent, + ScriptLanguage +} from '@app/shared/models/rule-node.models'; +import type { JsFuncComponent } from '@app/shared/components/js-func.component'; +import { AlarmSeverity, alarmSeverityTranslations } from '@app/shared/models/alarm.models'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; + +@Component({ + selector: 'tb-action-node-create-alarm-config', + templateUrl: './create-alarm-config.component.html', + styleUrls: [] +}) +export class CreateAlarmConfigComponent extends RuleNodeConfigurationComponent { + + @ViewChild('jsFuncComponent', {static: false}) jsFuncComponent: JsFuncComponent; + @ViewChild('tbelFuncComponent', {static: false}) tbelFuncComponent: JsFuncComponent; + + alarmSeverities = Object.keys(AlarmSeverity); + alarmSeverityTranslationMap = alarmSeverityTranslations; + createAlarmConfigForm: UntypedFormGroup; + + separatorKeysCodes = [ENTER, COMMA, SEMICOLON]; + + tbelEnabled = getCurrentAuthState(this.store).tbelEnabled; + + scriptLanguage = ScriptLanguage; + + changeScript: EventEmitter = new EventEmitter(); + + readonly hasScript = true; + + readonly testScriptLabel = 'tb.rulenode.test-details-function'; + + constructor(protected store: Store, + private fb: UntypedFormBuilder, + private nodeScriptTestService: NodeScriptTestService, + private translate: TranslateService) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.createAlarmConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.createAlarmConfigForm = this.fb.group({ + scriptLang: [configuration ? configuration.scriptLang : ScriptLanguage.JS, [Validators.required]], + alarmDetailsBuildJs: [configuration ? configuration.alarmDetailsBuildJs : null, []], + alarmDetailsBuildTbel: [configuration ? configuration.alarmDetailsBuildTbel : null, []], + useMessageAlarmData: [configuration ? configuration.useMessageAlarmData : false, []], + overwriteAlarmDetails: [configuration ? configuration.overwriteAlarmDetails : false, []], + alarmType: [configuration ? configuration.alarmType : null, []], + severity: [configuration ? configuration.severity : null, []], + propagate: [configuration ? configuration.propagate : false, []], + relationTypes: [configuration ? configuration.relationTypes : null, []], + propagateToOwner: [configuration ? configuration.propagateToOwner : false, []], + propagateToTenant: [configuration ? configuration.propagateToTenant : false, []], + dynamicSeverity: false + }); + + this.createAlarmConfigForm.get('dynamicSeverity').valueChanges.subscribe((dynamicSeverity) => { + if(dynamicSeverity){ + this.createAlarmConfigForm.get('severity').patchValue('',{emitEvent:false}); + } else { + this.createAlarmConfigForm.get('severity').patchValue(this.alarmSeverities[0],{emitEvent:false}); + } + }); + + } + + + protected validatorTriggers(): string[] { + return ['useMessageAlarmData', 'overwriteAlarmDetails', 'scriptLang']; + } + + protected updateValidators(emitEvent: boolean) { + const useMessageAlarmData: boolean = this.createAlarmConfigForm.get('useMessageAlarmData').value; + const overwriteAlarmDetails: boolean = this.createAlarmConfigForm.get('overwriteAlarmDetails').value; + if (useMessageAlarmData) { + this.createAlarmConfigForm.get('alarmType').setValidators([]); + this.createAlarmConfigForm.get('severity').setValidators([]); + } else { + this.createAlarmConfigForm.get('alarmType').setValidators([Validators.required]); + this.createAlarmConfigForm.get('severity').setValidators([Validators.required]); + } + this.createAlarmConfigForm.get('alarmType').updateValueAndValidity({emitEvent}); + this.createAlarmConfigForm.get('severity').updateValueAndValidity({emitEvent}); + + let scriptLang: ScriptLanguage = this.createAlarmConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.TBEL && !this.tbelEnabled) { + scriptLang = ScriptLanguage.JS; + this.createAlarmConfigForm.get('scriptLang').patchValue(scriptLang, {emitEvent: false}); + setTimeout(() => {this.createAlarmConfigForm.updateValueAndValidity({emitEvent: true});}); + } + const useAlarmDetailsBuildScript = useMessageAlarmData === false || overwriteAlarmDetails === true; + this.createAlarmConfigForm.get('alarmDetailsBuildJs') + .setValidators(useAlarmDetailsBuildScript && scriptLang === ScriptLanguage.JS ? [Validators.required] : []); + this.createAlarmConfigForm.get('alarmDetailsBuildTbel') + .setValidators(useAlarmDetailsBuildScript && scriptLang === ScriptLanguage.TBEL ? [Validators.required] : []); + this.createAlarmConfigForm.get('alarmDetailsBuildJs').updateValueAndValidity({emitEvent}); + this.createAlarmConfigForm.get('alarmDetailsBuildTbel').updateValueAndValidity({emitEvent}); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (configuration) { + if (!configuration.scriptLang) { + configuration.scriptLang = ScriptLanguage.JS; + } + } + return configuration; + } + + testScript(debugEventBody?: DebugRuleNodeEventBody) { + const scriptLang: ScriptLanguage = this.createAlarmConfigForm.get('scriptLang').value; + const scriptField = scriptLang === ScriptLanguage.JS ? 'alarmDetailsBuildJs' : 'alarmDetailsBuildTbel'; + const helpId = scriptLang === ScriptLanguage.JS ? 'rulenode/create_alarm_node_script_fn' : 'rulenode/tbel/create_alarm_node_script_fn'; + const script: string = this.createAlarmConfigForm.get(scriptField).value; + this.nodeScriptTestService.testNodeScript( + script, + 'json', + this.translate.instant('tb.rulenode.details'), + 'Details', + ['msg', 'metadata', 'msgType'], + this.ruleNodeId, + helpId, + scriptLang, + debugEventBody + ).subscribe((theScript) => { + if (theScript) { + this.createAlarmConfigForm.get(scriptField).setValue(theScript); + this.changeScript.emit(); + } + }); + } + + removeKey(key: string, keysField: string): void { + const keys: string[] = this.createAlarmConfigForm.get(keysField).value; + const index = keys.indexOf(key); + if (index >= 0) { + keys.splice(index, 1); + this.createAlarmConfigForm.get(keysField).setValue(keys, {emitEvent: true}); + } + } + + addKey(event: MatChipInputEvent, keysField: string): void { + const input = event.input; + let value = event.value; + if ((value || '').trim()) { + value = value.trim(); + let keys: string[] = this.createAlarmConfigForm.get(keysField).value; + if (!keys || keys.indexOf(value) === -1) { + if (!keys) { + keys = []; + } + keys.push(value); + this.createAlarmConfigForm.get(keysField).setValue(keys, {emitEvent: true}); + } + } + if (input) { + input.value = ''; + } + } + + protected onValidate() { + const useMessageAlarmData: boolean = this.createAlarmConfigForm.get('useMessageAlarmData').value; + const overwriteAlarmDetails: boolean = this.createAlarmConfigForm.get('overwriteAlarmDetails').value; + if (!useMessageAlarmData || overwriteAlarmDetails) { + const scriptLang: ScriptLanguage = this.createAlarmConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.JS) { + this.jsFuncComponent.validateOnSubmit(); + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.html new file mode 100644 index 0000000000..abbdb99f53 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.html @@ -0,0 +1,100 @@ + +
    +
    +
    tb.rulenode.relation-parameters
    +
    + + relation.direction + + + {{ directionTypeTranslations.get(type) | translate }} + + + + + +
    +
    + +
    +
    tb.rulenode.target-entity
    +
    + + + + + {{ entityTypeNamePatternTranslation.get(createRelationConfigForm.get('entityType').value) | translate }} + + + + + tb.rulenode.profile-name + + +
    + + + +
    + + {{ 'tb.rulenode.create-entity-if-not-exists' | translate }} + +
    +
    +
    + + + tb.rulenode.advanced-settings + +
    +
    + + {{ 'tb.rulenode.remove-current-relations' | translate }} + +
    +
    + + {{ 'tb.rulenode.change-originator-to-related-entity' | translate }} + +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts new file mode 100644 index 0000000000..53c8da3bd6 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-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 } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { EntitySearchDirection } from '@app/shared/models/relation.models'; +import { EntityType } from '@app/shared/models/entity-type.models'; + +@Component({ + selector: 'tb-action-node-create-relation-config', + templateUrl: './create-relation-config.component.html', + styleUrls: [] +}) +export class CreateRelationConfigComponent extends RuleNodeConfigurationComponent { + + directionTypes = Object.keys(EntitySearchDirection); + directionTypeTranslations = new Map( + [ + [EntitySearchDirection.FROM, 'tb.rulenode.search-direction-from'], + [EntitySearchDirection.TO, 'tb.rulenode.search-direction-to'], + ] + ); + + entityType = EntityType; + + entityTypeNamePatternTranslation = new Map( + [ + [EntityType.DEVICE, 'tb.rulenode.device-name-pattern'], + [EntityType.ASSET, 'tb.rulenode.asset-name-pattern'], + [EntityType.ENTITY_VIEW, 'tb.rulenode.entity-view-name-pattern'], + [EntityType.CUSTOMER, 'tb.rulenode.customer-title-pattern'], + [EntityType.USER, 'tb.rulenode.user-name-pattern'], + [EntityType.DASHBOARD, 'tb.rulenode.dashboard-name-pattern'], + [EntityType.EDGE, 'tb.rulenode.edge-name-pattern'] + ] + ); + + allowedEntityTypes = [EntityType.DEVICE, EntityType.ASSET, EntityType.ENTITY_VIEW, EntityType.TENANT, + EntityType.CUSTOMER, EntityType.USER, EntityType.DASHBOARD, EntityType.EDGE]; + + createRelationConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.createRelationConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.createRelationConfigForm = this.fb.group({ + direction: [configuration ? configuration.direction : null, [Validators.required]], + entityType: [configuration ? configuration.entityType : null, [Validators.required]], + entityNamePattern: [configuration ? configuration.entityNamePattern : null, []], + entityTypePattern: [configuration ? configuration.entityTypePattern : null, []], + relationType: [configuration ? configuration.relationType : null, [Validators.required]], + createEntityIfNotExists: [configuration ? configuration.createEntityIfNotExists : false, []], + removeCurrentRelations: [configuration ? configuration.removeCurrentRelations : false, []], + changeOriginatorToRelatedEntity: [configuration ? configuration.changeOriginatorToRelatedEntity : false, []] + }); + } + + protected validatorTriggers(): string[] { + return ['entityType', 'createEntityIfNotExists']; + } + + protected updateValidators(emitEvent: boolean) { + const entityType: EntityType = this.createRelationConfigForm.get('entityType').value; + if (entityType) { + this.createRelationConfigForm.get('entityNamePattern').setValidators([Validators.required, Validators.pattern(/.*\S.*/)]); + } else { + this.createRelationConfigForm.get('entityNamePattern').setValidators([]); + } + if (entityType && (entityType === EntityType.DEVICE || entityType === EntityType.ASSET)) { + const validators = [Validators.pattern(/.*\S.*/)] + if (this.createRelationConfigForm.get('createEntityIfNotExists').value) { + validators.push(Validators.required); + } + this.createRelationConfigForm.get('entityTypePattern').setValidators(validators); + } else { + this.createRelationConfigForm.get('entityTypePattern').setValidators([]); + } + this.createRelationConfigForm.get('entityNamePattern').updateValueAndValidity({emitEvent}); + this.createRelationConfigForm.get('entityTypePattern').updateValueAndValidity({emitEvent}); + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + configuration.entityNamePattern = configuration.entityNamePattern ? configuration.entityNamePattern.trim() : null; + configuration.entityTypePattern = configuration.entityTypePattern ? configuration.entityTypePattern.trim() : null; + return configuration; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.html new file mode 100644 index 0000000000..7050cae88a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.html @@ -0,0 +1,89 @@ + +
    +
    + + +
    + + {{ 'tb.rulenode.attributes-scope' | translate }} + + + {{ telemetryTypeTranslationsMap.get(scope) | translate }} + + + + + {{ 'tb.rulenode.attributes-scope-value' | translate }} + + + +
    +
    + + + {{ 'tb.rulenode.attributes-keys' | translate }} + + + {{key}} + close + + + + {{ 'tb.rulenode.attributes-keys-required' | translate }} + tb.rulenode.general-pattern-hint + + +
    + + + tb.rulenode.advanced-settings + +
    + + {{ 'tb.rulenode.send-attributes-deleted-notification' | translate }} + +
    +
    + + {{ 'tb.rulenode.notify-device' | translate }} + +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts new file mode 100644 index 0000000000..758e0ecb48 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts @@ -0,0 +1,88 @@ +/// +/// 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, ViewChild } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { MatChipGrid, MatChipInputEvent } from '@angular/material/chips'; +import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { AttributeScope, telemetryTypeTranslations } from '@shared/models/telemetry/telemetry.models'; + +@Component({ + selector: 'tb-action-node-delete-attributes-config', + templateUrl: './delete-attributes-config.component.html', + styleUrls: [] +}) +export class DeleteAttributesConfigComponent extends RuleNodeConfigurationComponent { + @ViewChild('attributeChipList') attributeChipList: MatChipGrid; + + deleteAttributesConfigForm: UntypedFormGroup; + attributeScopeMap = AttributeScope; + attributeScopes = Object.keys(AttributeScope); + telemetryTypeTranslationsMap = telemetryTypeTranslations; + separatorKeysCodes = [ENTER, COMMA, SEMICOLON]; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.deleteAttributesConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.deleteAttributesConfigForm = this.fb.group({ + scope: [configuration ? configuration.scope : null, [Validators.required]], + keys: [configuration ? configuration.keys : null, [Validators.required]], + sendAttributesDeletedNotification: [configuration ? configuration.sendAttributesDeletedNotification : false, []], + notifyDevice: [configuration ? configuration.notifyDevice : false, []] + }); + + this.deleteAttributesConfigForm.get('scope').valueChanges.subscribe((value) => { + if (value !== AttributeScope.SHARED_SCOPE) { + this.deleteAttributesConfigForm.get('notifyDevice').patchValue(false, {emitEvent: false}); + } + }); + } + + removeKey(key: string): void { + const keys: string[] = this.deleteAttributesConfigForm.get('keys').value; + const index = keys.indexOf(key); + if (index >= 0) { + keys.splice(index, 1); + this.deleteAttributesConfigForm.get('keys').patchValue(keys, {emitEvent: true}); + } + } + + addKey(event: MatChipInputEvent): void { + const input = event.input; + let value = event.value; + if ((value || '').trim()) { + value = value.trim(); + let keys: string[] = this.deleteAttributesConfigForm.get('keys').value; + if (!keys || keys.indexOf(value) === -1) { + if (!keys) { + keys = []; + } + keys.push(value); + this.deleteAttributesConfigForm.get('keys').patchValue(keys, {emitEvent: true}); + } + } + if (input) { + input.value = ''; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.html new file mode 100644 index 0000000000..bfd091dc57 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.html @@ -0,0 +1,62 @@ + +
    +
    +
    tb.rulenode.relation-parameters
    +
    + + relation.direction + + + {{ directionTypeTranslations.get(type) | translate }} + + + + + +
    +
    +
    +
    + + {{ 'tb.rulenode.delete-relation-with-specific-entity' | translate }} + +
    +
    +
    + + + + {{ entityTypeNamePatternTranslation.get(deleteRelationConfigForm.get('entityType').value) | translate }} + + +
    + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts new file mode 100644 index 0000000000..a59793f767 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts @@ -0,0 +1,101 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { EntityType } from '@app/shared/models/entity-type.models'; +import { EntitySearchDirection } from '@app/shared/models/relation.models'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-delete-relation-config', + templateUrl: './delete-relation-config.component.html', + styleUrls: [] +}) +export class DeleteRelationConfigComponent extends RuleNodeConfigurationComponent { + + directionTypes = Object.keys(EntitySearchDirection); + + directionTypeTranslations = new Map( + [ + [EntitySearchDirection.FROM, 'tb.rulenode.del-relation-direction-from'], + [EntitySearchDirection.TO, 'tb.rulenode.del-relation-direction-to'], + ] + ); + + entityTypeNamePatternTranslation = new Map( + [ + [EntityType.DEVICE, 'tb.rulenode.device-name-pattern'], + [EntityType.ASSET, 'tb.rulenode.asset-name-pattern'], + [EntityType.ENTITY_VIEW, 'tb.rulenode.entity-view-name-pattern'], + [EntityType.CUSTOMER, 'tb.rulenode.customer-title-pattern'], + [EntityType.USER, 'tb.rulenode.user-name-pattern'], + [EntityType.DASHBOARD, 'tb.rulenode.dashboard-name-pattern'], + [EntityType.EDGE, 'tb.rulenode.edge-name-pattern'] + ] + ); + + entityType = EntityType; + + allowedEntityTypes = [EntityType.DEVICE, EntityType.ASSET, EntityType.ENTITY_VIEW, EntityType.TENANT, + EntityType.CUSTOMER, EntityType.USER, EntityType.DASHBOARD, EntityType.EDGE]; + + deleteRelationConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.deleteRelationConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.deleteRelationConfigForm = this.fb.group({ + deleteForSingleEntity: [configuration ? configuration.deleteForSingleEntity : false, []], + direction: [configuration ? configuration.direction : null, [Validators.required]], + entityType: [configuration ? configuration.entityType : null, []], + entityNamePattern: [configuration ? configuration.entityNamePattern : null, []], + relationType: [configuration ? configuration.relationType : null, [Validators.required]] + }); + } + + protected validatorTriggers(): string[] { + return ['deleteForSingleEntity', 'entityType']; + } + + protected updateValidators(emitEvent: boolean) { + const deleteForSingleEntity: boolean = this.deleteRelationConfigForm.get('deleteForSingleEntity').value; + const entityType: EntityType = this.deleteRelationConfigForm.get('entityType').value; + if (deleteForSingleEntity) { + this.deleteRelationConfigForm.get('entityType').setValidators([Validators.required]); + } else { + this.deleteRelationConfigForm.get('entityType').setValidators([]); + } + if (deleteForSingleEntity && entityType && entityType !== EntityType.TENANT) { + this.deleteRelationConfigForm.get('entityNamePattern').setValidators([Validators.required, Validators.pattern(/.*\S.*/)]); + } else { + this.deleteRelationConfigForm.get('entityNamePattern').setValidators([]); + } + this.deleteRelationConfigForm.get('entityType').updateValueAndValidity({emitEvent: false}); + this.deleteRelationConfigForm.get('entityNamePattern').updateValueAndValidity({emitEvent}); + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + configuration.entityNamePattern = configuration.entityNamePattern ? configuration.entityNamePattern.trim() : null; + return configuration; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.html new file mode 100644 index 0000000000..bb897c6a2d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.html @@ -0,0 +1,32 @@ + +
    +
    tb.rulenode.device-profile-node-hint
    +
    + + {{ 'tb.rulenode.persist-alarm-rules' | translate }} + +
    +
    + + {{ 'tb.rulenode.fetch-alarm-rules' | translate }} + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.ts new file mode 100644 index 0000000000..7589475d87 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.ts @@ -0,0 +1,59 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-device-profile-config', + templateUrl: './device-profile-config.component.html', + styleUrls: [] +}) +export class DeviceProfileConfigComponent extends RuleNodeConfigurationComponent { + + deviceProfile: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.deviceProfile; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.deviceProfile = this.fb.group({ + persistAlarmRulesState: [configuration ? configuration.persistAlarmRulesState : false], + fetchAlarmRulesStateOnStart: [configuration ? configuration.fetchAlarmRulesStateOnStart : false] + }); + } + + protected validatorTriggers(): string[] { + return ['persistAlarmRulesState']; + } + + protected updateValidators(emitEvent: boolean) { + if (this.deviceProfile.get('persistAlarmRulesState').value) { + this.deviceProfile.get('fetchAlarmRulesStateOnStart').enable({emitEvent: false}); + } else { + this.deviceProfile.get('fetchAlarmRulesStateOnStart').setValue(false, {emitEvent: false}); + this.deviceProfile.get('fetchAlarmRulesStateOnStart').disable({emitEvent: false}); + } + this.deviceProfile.get('fetchAlarmRulesStateOnStart').updateValueAndValidity({emitEvent}); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.html new file mode 100644 index 0000000000..cae70173ff --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.html @@ -0,0 +1,27 @@ + +
    + + {{ 'tb.rulenode.select-device-connectivity-event' | translate }} + + + {{ messageTypeNames.get(eventOption) }} + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.ts new file mode 100644 index 0000000000..635b10f41b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.ts @@ -0,0 +1,59 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { MessageType, messageTypeNames, RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-device-state-config', + templateUrl: './device-state-config.component.html', + styleUrls: [] +}) +export class DeviceStateConfigComponent extends RuleNodeConfigurationComponent { + + deviceState: FormGroup; + + public messageTypeNames = messageTypeNames; + public eventOptions: MessageType[] = [ + MessageType.CONNECT_EVENT, + MessageType.ACTIVITY_EVENT, + MessageType.DISCONNECT_EVENT, + MessageType.INACTIVITY_EVENT + ]; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.deviceState; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + event: isDefinedAndNotNull(configuration?.event) ? configuration.event : MessageType.ACTIVITY_EVENT + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.deviceState = this.fb.group({ + event: [configuration.event, [Validators.required]] + }); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.html new file mode 100644 index 0000000000..a3ef3821bd --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.html @@ -0,0 +1,117 @@ + +
    +
    +
    tb.rulenode.generation-parameters
    +
    + + tb.rulenode.message-count + + + {{ 'tb.rulenode.message-count-required' | translate }} + + + {{ 'tb.rulenode.min-message-count-message' | translate }} + + + + tb.rulenode.generation-frequency-seconds + + + {{ 'tb.rulenode.generation-frequency-required' | translate }} + + + {{ 'tb.rulenode.min-generation-frequency-message' | translate }} + + +
    +
    + +
    +
    tb.rulenode.originator
    + + +
    +
    + + + tb.rulenode.generator-function + + + + + {{ 'tb.rulenode.script-lang-tbel' | translate }} + + + {{ 'tb.rulenode.script-lang-js' | translate }} + + + + + + + + {{ 'tb.rulenode.script-lang-tbel' | translate }} + + + {{ 'tb.rulenode.script-lang-js' | translate }} + + + + +
    + +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.scss new file mode 100644 index 0000000000..93c7934484 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.scss @@ -0,0 +1,51 @@ +/** + * 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 { + .mat-button-toggle-group { + min-width: 120px; + height: 24px !important; + .mat-button-toggle { + font-size: 0; + .mat-button-toggle-button { + height: 20px!important; + line-height: 20px !important; + border: none !important; + .mat-button-toggle-label-content { + font-size: 14px !important; + line-height: 20px !important; + } + } + } + } + .tb-entity-select { + @media screen and (min-width: 599px) { + display: flex; + flex-direction: row; + gap: 16px; + } + tb-entity-type-select { + flex: 1; + } + tb-entity-autocomplete { + flex: 1; + mat-form-field { + width: 100% !important; + } + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.ts new file mode 100644 index 0000000000..0524cfe546 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.ts @@ -0,0 +1,155 @@ +/// +/// 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, EventEmitter, ViewChild } from '@angular/core'; +import { getCurrentAuthState, isDefinedAndNotNull, NodeScriptTestService } from '@core/public-api'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { + RuleNodeConfiguration, + RuleNodeConfigurationComponent, + ScriptLanguage +} from '@app/shared/models/rule-node.models'; +import type { JsFuncComponent } from '@app/shared/components/js-func.component'; +import { EntityType } from '@app/shared/models/entity-type.models'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; + +@Component({ + selector: 'tb-action-node-generator-config', + templateUrl: './generator-config.component.html', + styleUrls: ['generator-config.component.scss'] +}) +export class GeneratorConfigComponent extends RuleNodeConfigurationComponent { + + @ViewChild('jsFuncComponent', {static: false}) jsFuncComponent: JsFuncComponent; + @ViewChild('tbelFuncComponent', {static: false}) tbelFuncComponent: JsFuncComponent; + + generatorConfigForm: UntypedFormGroup; + + tbelEnabled = getCurrentAuthState(this.store).tbelEnabled; + + scriptLanguage = ScriptLanguage; + + changeScript: EventEmitter = new EventEmitter(); + + allowedEntityTypes = [ + EntityType.DEVICE, EntityType.ASSET, EntityType.ENTITY_VIEW, EntityType.CUSTOMER, + EntityType.USER, EntityType.DASHBOARD + ]; + + additionEntityTypes = { + TENANT: this.translate.instant('tb.rulenode.current-tenant'), + RULE_NODE: this.translate.instant('tb.rulenode.current-rule-node') + }; + + readonly hasScript = true; + + readonly testScriptLabel = 'tb.rulenode.test-generator-function'; + + constructor(private fb: UntypedFormBuilder, + private nodeScriptTestService: NodeScriptTestService, + private translate: TranslateService) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.generatorConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.generatorConfigForm = this.fb.group({ + msgCount: [configuration ? configuration.msgCount : null, [Validators.required, Validators.min(0)]], + periodInSeconds: [configuration ? configuration.periodInSeconds : null, [Validators.required, Validators.min(1)]], + originator: [configuration ? configuration.originator : {id: null, entityType: EntityType.RULE_NODE}, []], + scriptLang: [configuration ? configuration.scriptLang : ScriptLanguage.JS, [Validators.required]], + jsScript: [configuration ? configuration.jsScript : null, []], + tbelScript: [configuration ? configuration.tbelScript : null, []] + }); + } + + protected validatorTriggers(): string[] { + return ['scriptLang']; + } + + protected updateValidators(emitEvent: boolean) { + let scriptLang: ScriptLanguage = this.generatorConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.TBEL && !this.tbelEnabled) { + scriptLang = ScriptLanguage.JS; + this.generatorConfigForm.get('scriptLang').patchValue(scriptLang, {emitEvent: false}); + setTimeout(() => {this.generatorConfigForm.updateValueAndValidity({emitEvent: true});}); + } + this.generatorConfigForm.get('jsScript').setValidators(scriptLang === ScriptLanguage.JS ? [Validators.required] : []); + this.generatorConfigForm.get('jsScript').updateValueAndValidity({emitEvent}); + this.generatorConfigForm.get('tbelScript').setValidators(scriptLang === ScriptLanguage.TBEL ? [Validators.required] : []); + this.generatorConfigForm.get('tbelScript').updateValueAndValidity({emitEvent}); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + msgCount: isDefinedAndNotNull(configuration?.msgCount) ? configuration?.msgCount : 0, + periodInSeconds: isDefinedAndNotNull(configuration?.periodInSeconds) ? configuration?.periodInSeconds : 1, + originator: { + id: isDefinedAndNotNull(configuration?.originatorId) ? configuration?.originatorId : null, + entityType: isDefinedAndNotNull(configuration?.originatorType) ? configuration?.originatorType : EntityType.RULE_NODE + }, + scriptLang: isDefinedAndNotNull(configuration?.scriptLang) ? configuration?.scriptLang : ScriptLanguage.JS, + tbelScript: isDefinedAndNotNull(configuration?.tbelScript) ? configuration?.tbelScript : null, + jsScript: isDefinedAndNotNull(configuration?.jsScript) ? configuration?.jsScript : null, + }; + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (configuration.originator) { + configuration.originatorId = configuration.originator.id; + configuration.originatorType = configuration.originator.entityType; + } else { + configuration.originatorId = null; + configuration.originatorType = null; + } + delete configuration.originator; + return configuration; + } + + testScript(debugEventBody?: DebugRuleNodeEventBody) { + const scriptLang: ScriptLanguage = this.generatorConfigForm.get('scriptLang').value; + const scriptField = scriptLang === ScriptLanguage.JS ? 'jsScript' : 'tbelScript'; + const helpId = scriptLang === ScriptLanguage.JS ? 'rulenode/generator_node_script_fn' : 'rulenode/tbel/generator_node_script_fn'; + const script: string = this.generatorConfigForm.get(scriptField).value; + this.nodeScriptTestService.testNodeScript( + script, + 'generate', + this.translate.instant('tb.rulenode.generator'), + 'Generate', + ['prevMsg', 'prevMetadata', 'prevMsgType'], + this.ruleNodeId, + helpId, + scriptLang, + debugEventBody + ).subscribe((theScript) => { + if (theScript) { + this.generatorConfigForm.get(scriptField).setValue(theScript); + this.changeScript.emit(); + } + }); + } + + protected onValidate() { + const scriptLang: ScriptLanguage = this.generatorConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.JS) { + this.jsFuncComponent.validateOnSubmit(); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.html new file mode 100644 index 0000000000..e76192aa9d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.html @@ -0,0 +1,195 @@ + +
    +
    +
    tb.rulenode.coordinate-field-names
    +
    +
    + + {{ 'tb.rulenode.latitude-field-name' | translate }} + + + {{ 'tb.rulenode.latitude-field-name-required' | translate }} + + + + {{ 'tb.rulenode.longitude-field-name' | translate }} + + + {{ 'tb.rulenode.longitude-field-name-required' | translate }} + + +
    +
    tb.rulenode.coordinate-field-hint
    +
    +
    +
    +
    tb.rulenode.geofence-configuration
    +
    + + {{ 'tb.rulenode.perimeter-type' | translate }} + + + {{ perimeterTypeTranslationMap.get(type) | translate }} + + + +
    + + {{ 'tb.rulenode.fetch-perimeter-info-from-metadata' | translate }} + +
    + + {{ 'tb.rulenode.perimeter-key-name' | translate }} + + + {{ 'tb.rulenode.perimeter-key-name-required' | translate }} + + {{ 'tb.rulenode.perimeter-key-name-hint' | translate }} + +
    +
    + + {{ 'tb.rulenode.circle-center-latitude' | translate }} + + + {{ 'tb.rulenode.circle-center-latitude-required' | translate }} + + + + {{ 'tb.rulenode.circle-center-longitude' | translate }} + + + {{ 'tb.rulenode.circle-center-longitude-required' | translate }} + + +
    +
    + + {{ 'tb.rulenode.range' | translate }} + + + {{ 'tb.rulenode.range-required' | translate }} + + + + {{ 'tb.rulenode.range-units' | translate }} + + + {{ rangeUnitTranslationMap.get(type) | translate }} + + + + {{ 'tb.rulenode.range-units-required' | translate }} + + +
    +
    +
    + + tb.rulenode.polygon-definition + + + help + + + {{ 'tb.rulenode.polygon-definition-required' | translate }} + + +
    +
    +
    +
    +
    +
    {{ 'tb.rulenode.presence-monitoring-strategy' | translate }}
    + + + {{ presenceMonitoringStrategies.get(strategy).name | translate }} + + +
    +
    {{ geoActionConfigForm.get('reportPresenceStatusOnEachMessage').value === false ? + ('tb.rulenode.presence-monitoring-strategy-on-first-message-hint' | translate) : + ('tb.rulenode.presence-monitoring-strategy-on-each-message-hint' | translate) }} +
    +
    +
    +
    + + tb.rulenode.min-inside-duration + + + {{ 'tb.rulenode.min-inside-duration-value-required' | translate }} + + + {{ 'tb.rulenode.time-value-range' | translate }} + + + {{ 'tb.rulenode.time-value-range' | translate }} + + + + tb.rulenode.min-inside-duration-time-unit + + + {{ timeUnitsTranslationMap.get(timeUnit) | translate }} + + + +
    +
    + + tb.rulenode.min-outside-duration + + + {{ 'tb.rulenode.min-outside-duration-value-required' | translate }} + + + {{ 'tb.rulenode.time-value-range' | translate }} + + + {{ 'tb.rulenode.time-value-range' | translate }} + + + + tb.rulenode.min-outside-duration-time-unit + + + {{ timeUnitsTranslationMap.get(timeUnit) | translate }} + + + +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.scss new file mode 100644 index 0000000000..f177555e37 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.scss @@ -0,0 +1,20 @@ +/** + * 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 { + .slide-toggle { + margin-bottom: 18px; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.ts new file mode 100644 index 0000000000..47347edadf --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/gps-geo-action-config.component.ts @@ -0,0 +1,126 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { + PerimeterType, + perimeterTypeTranslations, + PresenceMonitoringStrategiesData, + RangeUnit, + rangeUnitTranslations, + TimeUnit, + timeUnitTranslations +} from '../rule-node-config.models'; + +@Component({ + selector: 'tb-action-node-gps-geofencing-config', + templateUrl: './gps-geo-action-config.component.html', + styleUrls: ['./gps-geo-action-config.component.scss'] +}) +export class GpsGeoActionConfigComponent extends RuleNodeConfigurationComponent { + + geoActionConfigForm: UntypedFormGroup; + + perimeterType = PerimeterType; + perimeterTypes = Object.keys(PerimeterType); + perimeterTypeTranslationMap = perimeterTypeTranslations; + + rangeUnits = Object.keys(RangeUnit); + rangeUnitTranslationMap = rangeUnitTranslations; + + presenceMonitoringStrategies = PresenceMonitoringStrategiesData; + presenceMonitoringStrategyKeys = Array.from(this.presenceMonitoringStrategies.keys()); + + timeUnits = Object.keys(TimeUnit); + timeUnitsTranslationMap = timeUnitTranslations; + + public defaultPaddingEnable = true; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.geoActionConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.geoActionConfigForm = this.fb.group({ + reportPresenceStatusOnEachMessage: [configuration ? configuration.reportPresenceStatusOnEachMessage : true, + [Validators.required]], + latitudeKeyName: [configuration ? configuration.latitudeKeyName : null, [Validators.required]], + longitudeKeyName: [configuration ? configuration.longitudeKeyName : null, [Validators.required]], + perimeterType: [configuration ? configuration.perimeterType : null, [Validators.required]], + fetchPerimeterInfoFromMessageMetadata: [configuration ? configuration.fetchPerimeterInfoFromMessageMetadata : false, []], + perimeterKeyName: [configuration ? configuration.perimeterKeyName : null, []], + centerLatitude: [configuration ? configuration.centerLatitude : null, []], + centerLongitude: [configuration ? configuration.centerLatitude : null, []], + range: [configuration ? configuration.range : null, []], + rangeUnit: [configuration ? configuration.rangeUnit : null, []], + polygonsDefinition: [configuration ? configuration.polygonsDefinition : null, []], + minInsideDuration: [configuration ? configuration.minInsideDuration : null, + [Validators.required, Validators.min(1), Validators.max(2147483647)]], + minInsideDurationTimeUnit: [configuration ? configuration.minInsideDurationTimeUnit : null, [Validators.required]], + minOutsideDuration: [configuration ? configuration.minOutsideDuration : null, + [Validators.required, Validators.min(1), Validators.max(2147483647)]], + minOutsideDurationTimeUnit: [configuration ? configuration.minOutsideDurationTimeUnit : null, [Validators.required]], + }); + } + + protected validatorTriggers(): string[] { + return ['fetchPerimeterInfoFromMessageMetadata', 'perimeterType']; + } + + protected updateValidators(emitEvent: boolean) { + const fetchPerimeterInfoFromMessageMetadata: boolean = this.geoActionConfigForm.get('fetchPerimeterInfoFromMessageMetadata').value; + const perimeterType: PerimeterType = this.geoActionConfigForm.get('perimeterType').value; + if (fetchPerimeterInfoFromMessageMetadata) { + this.geoActionConfigForm.get('perimeterKeyName').setValidators([Validators.required]); + } else { + this.geoActionConfigForm.get('perimeterKeyName').setValidators([]); + } + if (!fetchPerimeterInfoFromMessageMetadata && perimeterType === PerimeterType.CIRCLE) { + this.geoActionConfigForm.get('centerLatitude').setValidators([Validators.required, + Validators.min(-90), Validators.max(90)]); + this.geoActionConfigForm.get('centerLongitude').setValidators([Validators.required, + Validators.min(-180), Validators.max(180)]); + this.geoActionConfigForm.get('range').setValidators([Validators.required, Validators.min(0)]); + this.geoActionConfigForm.get('rangeUnit').setValidators([Validators.required]); + + this.defaultPaddingEnable = false; + } else { + this.geoActionConfigForm.get('centerLatitude').setValidators([]); + this.geoActionConfigForm.get('centerLongitude').setValidators([]); + this.geoActionConfigForm.get('range').setValidators([]); + this.geoActionConfigForm.get('rangeUnit').setValidators([]); + + this.defaultPaddingEnable = true; + } + if (!fetchPerimeterInfoFromMessageMetadata && perimeterType === PerimeterType.POLYGON) { + this.geoActionConfigForm.get('polygonsDefinition').setValidators([Validators.required]); + } else { + this.geoActionConfigForm.get('polygonsDefinition').setValidators([]); + } + this.geoActionConfigForm.get('perimeterKeyName').updateValueAndValidity({emitEvent}); + this.geoActionConfigForm.get('centerLatitude').updateValueAndValidity({emitEvent}); + this.geoActionConfigForm.get('centerLongitude').updateValueAndValidity({emitEvent}); + this.geoActionConfigForm.get('range').updateValueAndValidity({emitEvent}); + this.geoActionConfigForm.get('rangeUnit').updateValueAndValidity({emitEvent}); + this.geoActionConfigForm.get('polygonsDefinition').updateValueAndValidity({emitEvent}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.html new file mode 100644 index 0000000000..c47644ae5f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.html @@ -0,0 +1,59 @@ + +
    + + + + + + + +
    + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.ts new file mode 100644 index 0000000000..dab86ae14d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/log-config.component.ts @@ -0,0 +1,124 @@ +/// +/// 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, EventEmitter, ViewChild } from '@angular/core'; +import { getCurrentAuthState, NodeScriptTestService } from '@core/public-api'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { + RuleNodeConfiguration, + RuleNodeConfigurationComponent, + ScriptLanguage +} from '@app/shared/models/rule-node.models'; +import type { JsFuncComponent } from '@app/shared/components/js-func.component'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; + +@Component({ + selector: 'tb-action-node-log-config', + templateUrl: './log-config.component.html', + styleUrls: [] +}) +export class LogConfigComponent extends RuleNodeConfigurationComponent { + + @ViewChild('jsFuncComponent', {static: false}) jsFuncComponent: JsFuncComponent; + @ViewChild('tbelFuncComponent', {static: false}) tbelFuncComponent: JsFuncComponent; + + logConfigForm: UntypedFormGroup; + + tbelEnabled = getCurrentAuthState(this.store).tbelEnabled; + + scriptLanguage = ScriptLanguage; + + changeScript: EventEmitter = new EventEmitter(); + + readonly hasScript = true; + + readonly testScriptLabel = 'tb.rulenode.test-to-string-function'; + + constructor(private fb: UntypedFormBuilder, + private nodeScriptTestService: NodeScriptTestService, + private translate: TranslateService) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.logConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.logConfigForm = this.fb.group({ + scriptLang: [configuration ? configuration.scriptLang : ScriptLanguage.JS, [Validators.required]], + jsScript: [configuration ? configuration.jsScript : null, []], + tbelScript: [configuration ? configuration.tbelScript : null, []] + }); + } + + protected validatorTriggers(): string[] { + return ['scriptLang']; + } + + protected updateValidators(emitEvent: boolean) { + let scriptLang: ScriptLanguage = this.logConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.TBEL && !this.tbelEnabled) { + scriptLang = ScriptLanguage.JS; + this.logConfigForm.get('scriptLang').patchValue(scriptLang, {emitEvent: false}); + setTimeout(() => {this.logConfigForm.updateValueAndValidity({emitEvent: true});}); + } + this.logConfigForm.get('jsScript').setValidators(scriptLang === ScriptLanguage.JS ? [Validators.required] : []); + this.logConfigForm.get('jsScript').updateValueAndValidity({emitEvent}); + this.logConfigForm.get('tbelScript').setValidators(scriptLang === ScriptLanguage.TBEL ? [Validators.required] : []); + this.logConfigForm.get('tbelScript').updateValueAndValidity({emitEvent}); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (configuration) { + if (!configuration.scriptLang) { + configuration.scriptLang = ScriptLanguage.JS; + } + } + return configuration; + } + + testScript(debugEventBody?: DebugRuleNodeEventBody) { + const scriptLang: ScriptLanguage = this.logConfigForm.get('scriptLang').value; + const scriptField = scriptLang === ScriptLanguage.JS ? 'jsScript' : 'tbelScript'; + const helpId = scriptLang === ScriptLanguage.JS ? 'rulenode/log_node_script_fn' : 'rulenode/tbel/log_node_script_fn'; + const script: string = this.logConfigForm.get(scriptField).value; + this.nodeScriptTestService.testNodeScript( + script, + 'string', + this.translate.instant('tb.rulenode.to-string'), + 'ToString', + ['msg', 'metadata', 'msgType'], + this.ruleNodeId, + helpId, + scriptLang, + debugEventBody + ).subscribe((theScript) => { + if (theScript) { + this.logConfigForm.get(scriptField).setValue(theScript); + this.changeScript.emit(); + } + }); + } + + protected onValidate() { + const scriptLang: ScriptLanguage = this.logConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.JS) { + this.jsFuncComponent.validateOnSubmit(); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.html new file mode 100644 index 0000000000..4da207aacb --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.html @@ -0,0 +1,103 @@ + +
    + + +
    + tb.rulenode.argument-tile + + +
    +
    + {{'tb.rulenode.custom-expression-field-input' | translate }} * + + + + tb.rulenode.custom-expression-field-input-required + + tb.rulenode.custom-expression-field-input-hint + +
    +
    + tb.rulenode.result-title +
    + + tb.rulenode.type-field-input + + + {{ argumentTypeResultMap.get(mathFunctionConfigForm.get('result.type').value)?.name | translate }} + + + {{ argumentTypeResultMap.get(argument).name | translate }} + + {{ argumentTypeResultMap.get(argument).description }} + + + + + tb.rulenode.type-field-input-required + + +
    + + tb.rulenode.attribute-scope-field-input + + + {{ attributeScopeMap.get(scope) | translate }} + + + + + tb.rulenode.key-field-input + + help + + tb.rulenode.key-field-input-required + + +
    +
    + + tb.rulenode.number-floating-point-field-input + + + +
    +
    + + {{'tb.rulenode.add-to-message-field-input' | translate }} + + + {{'tb.rulenode.add-to-metadata-field-input' | translate}} + +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.scss new file mode 100644 index 0000000000..d96fbe7578 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.scss @@ -0,0 +1,41 @@ +/** + * 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 { + .fields-group { + padding: 0 16px 8px; + margin: 10px 0; + border: 1px groove rgba(0, 0, 0, .25); + border-radius: 4px; + + .mat-mdc-form-field { + .mat-mdc-form-field-infix { + width: 100%; + } + } + + legend { + color: rgba(0, 0, 0, .7); + width: fit-content; + } + + legend + * { + display: block; + &.no-margin-top { + margin-top: 0; + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.ts new file mode 100644 index 0000000000..2ff796840e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/math-function-config.component.ts @@ -0,0 +1,92 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { + ArgumentTypeResult, + ArgumentTypeResultMap, + AttributeScopeMap, + AttributeScopeResult, + MathFunction +} from '../rule-node-config.models'; + + +@Component({ + selector: 'tb-action-node-math-function-config', + templateUrl: './math-function-config.component.html', + styleUrls: ['./math-function-config.component.scss'] +}) +export class MathFunctionConfigComponent extends RuleNodeConfigurationComponent { + + mathFunctionConfigForm: UntypedFormGroup; + + MathFunction = MathFunction; + ArgumentTypeResult = ArgumentTypeResult; + argumentTypeResultMap = ArgumentTypeResultMap; + attributeScopeMap = AttributeScopeMap; + argumentsResult = Object.values(ArgumentTypeResult); + attributeScopeResult = Object.values(AttributeScopeResult); + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.mathFunctionConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.mathFunctionConfigForm = this.fb.group({ + operation: [configuration ? configuration.operation : null, [Validators.required]], + arguments: [configuration ? configuration.arguments : null, [Validators.required]], + customFunction: [configuration ? configuration.customFunction : '', [Validators.required]], + result: this.fb.group({ + type: [configuration ? configuration.result.type: null, [Validators.required]], + attributeScope: [configuration ? configuration.result.attributeScope : null, [Validators.required]], + key: [configuration ? configuration.result.key : '', [Validators.required]], + resultValuePrecision: [configuration ? configuration.result.resultValuePrecision : 0], + addToBody: [configuration ? configuration.result.addToBody : false], + addToMetadata: [configuration ? configuration.result.addToMetadata : false] + }) + }); + } + + protected updateValidators(emitEvent: boolean) { + const operation: MathFunction = this.mathFunctionConfigForm.get('operation').value; + const resultType: ArgumentTypeResult = this.mathFunctionConfigForm.get('result.type').value; + if (operation === MathFunction.CUSTOM) { + this.mathFunctionConfigForm.get('customFunction').enable({emitEvent: false}); + if (this.mathFunctionConfigForm.get('customFunction').value === null) { + this.mathFunctionConfigForm.get('customFunction').patchValue('(x - 32) / 1.8', {emitEvent: false}); + } + } else { + this.mathFunctionConfigForm.get('customFunction').disable({emitEvent: false}); + } + if (resultType === ArgumentTypeResult.ATTRIBUTE) { + this.mathFunctionConfigForm.get('result.attributeScope').enable({emitEvent: false}); + } else { + this.mathFunctionConfigForm.get('result.attributeScope').disable({emitEvent: false}); + } + this.mathFunctionConfigForm.get('customFunction').updateValueAndValidity({emitEvent}); + this.mathFunctionConfigForm.get('result.attributeScope').updateValueAndValidity({emitEvent}); + } + + protected validatorTriggers(): string[] { + return ['operation', 'result.type']; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.html new file mode 100644 index 0000000000..e013fc1d5d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.html @@ -0,0 +1,36 @@ + +
    + + tb.rulenode.interval-seconds + + + {{ 'tb.rulenode.interval-seconds-required' | translate }} + + + {{ 'tb.rulenode.min-interval-seconds-message' | translate }} + + + + tb.rulenode.output-timeseries-key-prefix + + + {{ 'tb.rulenode.output-timeseries-key-prefix-required' | translate }} + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.ts new file mode 100644 index 0000000000..5380c569a0 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-count-config.component.ts @@ -0,0 +1,45 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-msg-count-config', + templateUrl: './msg-count-config.component.html', + styleUrls: [] +}) +export class MsgCountConfigComponent extends RuleNodeConfigurationComponent { + + msgCountConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.msgCountConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.msgCountConfigForm = this.fb.group({ + interval: [configuration ? configuration.interval : null, [Validators.required, Validators.min(1)]], + telemetryPrefix: [configuration ? configuration.telemetryPrefix : null, [Validators.required]] + }); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.html new file mode 100644 index 0000000000..677228b7bc --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.html @@ -0,0 +1,57 @@ + +
    + + {{ 'tb.rulenode.use-metadata-period-in-seconds-patterns' | translate }} + +
    tb.rulenode.use-metadata-period-in-seconds-patterns-hint
    + + tb.rulenode.period-seconds + + + {{ 'tb.rulenode.period-seconds-required' | translate }} + + + {{ 'tb.rulenode.min-period-0-seconds-message' | translate }} + + + + + tb.rulenode.period-in-seconds-pattern + + + {{ 'tb.rulenode.period-in-seconds-pattern-required' | translate }} + + tb.rulenode.general-pattern-hint + + + + tb.rulenode.max-pending-messages + + + {{ 'tb.rulenode.max-pending-messages-required' | translate }} + + + {{ 'tb.rulenode.max-pending-messages-range' | translate }} + + + {{ 'tb.rulenode.max-pending-messages-range' | translate }} + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.ts new file mode 100644 index 0000000000..cabf2e67af --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/msg-delay-config.component.ts @@ -0,0 +1,65 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-msg-delay-config', + templateUrl: './msg-delay-config.component.html', + styleUrls: [] +}) +export class MsgDelayConfigComponent extends RuleNodeConfigurationComponent { + + msgDelayConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.msgDelayConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.msgDelayConfigForm = this.fb.group({ + useMetadataPeriodInSecondsPatterns: [configuration ? configuration.useMetadataPeriodInSecondsPatterns : false, []], + periodInSeconds: [configuration ? configuration.periodInSeconds : null, []], + periodInSecondsPattern: [configuration ? configuration.periodInSecondsPattern : null, []], + maxPendingMsgs: [configuration ? configuration.maxPendingMsgs : null, + [Validators.required, Validators.min(1), Validators.max(100000)]], + }); + } + + protected validatorTriggers(): string[] { + return ['useMetadataPeriodInSecondsPatterns']; + } + + protected updateValidators(emitEvent: boolean) { + const useMetadataPeriodInSecondsPatterns: boolean = this.msgDelayConfigForm.get('useMetadataPeriodInSecondsPatterns').value; + if (useMetadataPeriodInSecondsPatterns) { + this.msgDelayConfigForm.get('periodInSecondsPattern').setValidators([Validators.required]); + this.msgDelayConfigForm.get('periodInSeconds').setValidators([]); + } else { + this.msgDelayConfigForm.get('periodInSecondsPattern').setValidators([]); + this.msgDelayConfigForm.get('periodInSeconds').setValidators([Validators.required, Validators.min(0)]); + } + this.msgDelayConfigForm.get('periodInSecondsPattern').updateValueAndValidity({emitEvent}); + this.msgDelayConfigForm.get('periodInSeconds').updateValueAndValidity({emitEvent}); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.html new file mode 100644 index 0000000000..8e37d85c47 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.html @@ -0,0 +1,49 @@ + +
    +
    + + +
    + + {{ 'tb.rulenode.attributes-scope' | translate }} + + + {{ telemetryTypeTranslationsMap.get(scope) | translate }} + + + + + {{ 'tb.rulenode.attributes-scope-value' | translate }} + + + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.ts new file mode 100644 index 0000000000..07082ebabe --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-cloud-config.component.ts @@ -0,0 +1,48 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { AttributeScope, telemetryTypeTranslations } from '@shared/models/telemetry/telemetry.models'; + +@Component({ + selector: 'tb-action-node-push-to-cloud-config', + templateUrl: './push-to-cloud-config.component.html', + styleUrls: [] +}) +export class PushToCloudConfigComponent extends RuleNodeConfigurationComponent { + + attributeScopes = Object.keys(AttributeScope); + telemetryTypeTranslationsMap = telemetryTypeTranslations; + + pushToCloudConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.pushToCloudConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.pushToCloudConfigForm = this.fb.group({ + scope: [configuration ? configuration.scope : null, [Validators.required]] + }); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.html new file mode 100644 index 0000000000..6c3088fc23 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.html @@ -0,0 +1,49 @@ + +
    +
    + + +
    + + {{ 'tb.rulenode.attributes-scope' | translate }} + + + {{ telemetryTypeTranslationsMap.get(scope) | translate }} + + + + + {{ 'tb.rulenode.attributes-scope-value' | translate }} + + + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.ts new file mode 100644 index 0000000000..bbefcd3d76 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/push-to-edge-config.component.ts @@ -0,0 +1,48 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { AttributeScope, telemetryTypeTranslations } from '@shared/models/telemetry/telemetry.models'; + +@Component({ + selector: 'tb-action-node-push-to-edge-config', + templateUrl: './push-to-edge-config.component.html', + styleUrls: [] +}) +export class PushToEdgeConfigComponent extends RuleNodeConfigurationComponent { + + attributeScopes = Object.keys(AttributeScope); + telemetryTypeTranslationsMap = telemetryTypeTranslations; + + pushToEdgeConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.pushToEdgeConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.pushToEdgeConfigForm = this.fb.group({ + scope: [configuration ? configuration.scope : null, [Validators.required]] + }); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.html new file mode 100644 index 0000000000..b4ec4b5047 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.html @@ -0,0 +1,36 @@ + +
    +
    tb.rulenode.reply-routing-configuration
    + + +
    + + tb.rulenode.service-id-metadata-attribute + + + + tb.rulenode.session-id-metadata-attribute + + + + tb.rulenode.request-id-metadata-attribute + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.ts new file mode 100644 index 0000000000..840c6eb9c3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-reply-config.component.ts @@ -0,0 +1,45 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-rpc-reply-config', + templateUrl: './rpc-reply-config.component.html', + styleUrls: [] +}) +export class RpcReplyConfigComponent extends RuleNodeConfigurationComponent { + + rpcReplyConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.rpcReplyConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.rpcReplyConfigForm = this.fb.group({ + serviceIdMetaDataAttribute: [configuration ? configuration.serviceIdMetaDataAttribute : null, []], + sessionIdMetaDataAttribute: [configuration ? configuration.sessionIdMetaDataAttribute : null, []], + requestIdMetaDataAttribute: [configuration ? configuration.requestIdMetaDataAttribute : null, []] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.html new file mode 100644 index 0000000000..2673c7e9f3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.html @@ -0,0 +1,29 @@ + +
    + + tb.rulenode.timeout-sec + + + {{ 'tb.rulenode.timeout-required' | translate }} + + + {{ 'tb.rulenode.min-timeout-message' | translate }} + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.ts new file mode 100644 index 0000000000..d54677b237 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/rpc-request-config.component.ts @@ -0,0 +1,43 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-rpc-request-config', + templateUrl: './rpc-request-config.component.html', + styleUrls: [] +}) +export class RpcRequestConfigComponent extends RuleNodeConfigurationComponent { + + rpcRequestConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.rpcRequestConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.rpcRequestConfigForm = this.fb.group({ + timeoutInSeconds: [configuration ? configuration.timeoutInSeconds : null, [Validators.required, Validators.min(0)]] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/rule-node-config-action.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/rule-node-config-action.module.ts new file mode 100644 index 0000000000..8c8350378d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/rule-node-config-action.module.ts @@ -0,0 +1,132 @@ +/// +/// 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 { NgModule, Type } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { HomeComponentsModule } from '@home/components/public-api'; +import { AttributesConfigComponent } from './attributes-config.component'; +import { TimeseriesConfigComponent } from './timeseries-config.component'; +import { RpcRequestConfigComponent } from './rpc-request-config.component'; +import { LogConfigComponent } from './log-config.component'; +import { AssignCustomerConfigComponent } from './assign-customer-config.component'; +import { ClearAlarmConfigComponent } from './clear-alarm-config.component'; +import { CreateAlarmConfigComponent } from './create-alarm-config.component'; +import { CreateRelationConfigComponent } from './create-relation-config.component'; +import { MsgDelayConfigComponent } from './msg-delay-config.component'; +import { DeleteRelationConfigComponent } from './delete-relation-config.component'; +import { GeneratorConfigComponent } from './generator-config.component'; +import { GpsGeoActionConfigComponent } from './gps-geo-action-config.component'; +import { MsgCountConfigComponent } from './msg-count-config.component'; +import { RpcReplyConfigComponent } from './rpc-reply-config.component'; +import { SaveToCustomTableConfigComponent } from './save-to-custom-table-config.component'; +import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.module'; +import { UnassignCustomerConfigComponent } from './unassign-customer-config.component'; +import { DeviceProfileConfigComponent } from './device-profile-config.component'; +import { PushToEdgeConfigComponent } from './push-to-edge-config.component'; +import { PushToCloudConfigComponent } from './push-to-cloud-config.component'; +import { DeleteAttributesConfigComponent } from './delete-attributes-config.component'; +import { MathFunctionConfigComponent } from './math-function-config.component'; +import { DeviceStateConfigComponent } from './device-state-config.component'; +import { SendRestApiCallReplyConfigComponent } from './send-rest-api-call-reply-config.component'; +import { EmptyConfigComponent } from '@home/components/rule-node/empty-config.component'; + +@NgModule({ + declarations: [ + DeleteAttributesConfigComponent, + AttributesConfigComponent, + TimeseriesConfigComponent, + RpcRequestConfigComponent, + LogConfigComponent, + AssignCustomerConfigComponent, + ClearAlarmConfigComponent, + CreateAlarmConfigComponent, + CreateRelationConfigComponent, + MsgDelayConfigComponent, + DeleteRelationConfigComponent, + GeneratorConfigComponent, + GpsGeoActionConfigComponent, + MsgCountConfigComponent, + RpcReplyConfigComponent, + SaveToCustomTableConfigComponent, + UnassignCustomerConfigComponent, + SendRestApiCallReplyConfigComponent, + DeviceProfileConfigComponent, + PushToEdgeConfigComponent, + PushToCloudConfigComponent, + MathFunctionConfigComponent, + DeviceStateConfigComponent + ], + imports: [ + CommonModule, + SharedModule, + HomeComponentsModule, + RuleNodeConfigCommonModule + ], + exports: [ + DeleteAttributesConfigComponent, + AttributesConfigComponent, + TimeseriesConfigComponent, + RpcRequestConfigComponent, + LogConfigComponent, + AssignCustomerConfigComponent, + ClearAlarmConfigComponent, + CreateAlarmConfigComponent, + CreateRelationConfigComponent, + MsgDelayConfigComponent, + DeleteRelationConfigComponent, + GeneratorConfigComponent, + GpsGeoActionConfigComponent, + MsgCountConfigComponent, + RpcReplyConfigComponent, + SaveToCustomTableConfigComponent, + UnassignCustomerConfigComponent, + SendRestApiCallReplyConfigComponent, + DeviceProfileConfigComponent, + PushToEdgeConfigComponent, + PushToCloudConfigComponent, + MathFunctionConfigComponent, + DeviceStateConfigComponent + ] +}) +export class RuleNodeConfigActionModule { +} + +export const ruleNodeActionConfigComponentsMap: Record> = { + 'tbActionNodeAssignToCustomerConfig': AssignCustomerConfigComponent, + 'tbActionNodeAttributesConfig': AttributesConfigComponent, + 'tbActionNodeClearAlarmConfig': ClearAlarmConfigComponent, + 'tbActionNodeCreateAlarmConfig': CreateAlarmConfigComponent, + 'tbActionNodeCreateRelationConfig': CreateRelationConfigComponent, + 'tbActionNodeDeleteAttributesConfig': DeleteAttributesConfigComponent, + 'tbActionNodeDeleteRelationConfig': DeleteRelationConfigComponent, + 'tbDeviceProfileConfig': DeviceProfileConfigComponent, + 'tbActionNodeDeviceStateConfig': DeviceStateConfigComponent, + 'tbActionNodeGeneratorConfig': GeneratorConfigComponent, + 'tbActionNodeGpsGeofencingConfig': GpsGeoActionConfigComponent, + 'tbActionNodeLogConfig': LogConfigComponent, + 'tbActionNodeMathFunctionConfig': MathFunctionConfigComponent, + 'tbActionNodeMsgCountConfig': MsgCountConfigComponent, + 'tbActionNodeMsgDelayConfig': MsgDelayConfigComponent, + 'tbActionNodePushToCloudConfig': PushToCloudConfigComponent, + 'tbActionNodePushToEdgeConfig': PushToEdgeConfigComponent, + 'tbActionNodeRpcReplyConfig': RpcReplyConfigComponent, + 'tbActionNodeRpcRequestConfig': RpcRequestConfigComponent, + 'tbActionNodeCustomTableConfig': SaveToCustomTableConfigComponent, + 'tbActionNodeSendRestApiCallReplyConfig': SendRestApiCallReplyConfigComponent, + 'tbActionNodeTimeseriesConfig': TimeseriesConfigComponent, + 'tbActionNodeUnAssignToCustomerConfig': UnassignCustomerConfigComponent +}; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.html new file mode 100644 index 0000000000..61790d8537 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.html @@ -0,0 +1,56 @@ + +
    + + tb.rulenode.custom-table-name + + + help + + + {{ 'tb.rulenode.custom-table-name-required' | translate }} + + + + + + tb.rulenode.default-ttl + + tb.rulenode.default-ttl-zero-hint + + {{ 'tb.rulenode.min-default-ttl-message' | translate }} + + + {{ 'tb.rulenode.default-ttl-required' | translate }} + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.ts new file mode 100644 index 0000000000..27d40dd4b9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/save-to-custom-table-config.component.ts @@ -0,0 +1,50 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-custom-table-config', + templateUrl: './save-to-custom-table-config.component.html', + styleUrls: [] +}) +export class SaveToCustomTableConfigComponent extends RuleNodeConfigurationComponent { + + saveToCustomTableConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.saveToCustomTableConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.saveToCustomTableConfigForm = this.fb.group({ + tableName: [configuration ? configuration.tableName : null, [Validators.required, Validators.pattern(/.*\S.*/)]], + fieldsMapping: [configuration ? configuration.fieldsMapping : null, [Validators.required]], + defaultTtl: [configuration ? configuration.defaultTtl : 0, [Validators.required, Validators.min(0)]] + }); + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + configuration.tableName = configuration.tableName.trim(); + return configuration; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.html new file mode 100644 index 0000000000..b1cbce5042 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.html @@ -0,0 +1,32 @@ + +
    +
    tb.rulenode.reply-routing-configuration
    + + +
    + + tb.rulenode.service-id-metadata-attribute + + + + tb.rulenode.request-id-metadata-attribute + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.ts new file mode 100644 index 0000000000..ad4e148658 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/send-rest-api-call-reply-config.component.ts @@ -0,0 +1,44 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-send-rest-api-call-reply-config', + templateUrl: './send-rest-api-call-reply-config.component.html', + styleUrls: [] +}) +export class SendRestApiCallReplyConfigComponent extends RuleNodeConfigurationComponent { + + sendRestApiCallReplyConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.sendRestApiCallReplyConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.sendRestApiCallReplyConfigForm = this.fb.group({ + requestIdMetaDataAttribute: [configuration ? configuration.requestIdMetaDataAttribute : null, []], + serviceIdMetaDataAttribute: [configuration ? configuration.serviceIdMetaDataAttribute : null, []] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.html new file mode 100644 index 0000000000..0635232e48 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.html @@ -0,0 +1,50 @@ + +
    + + tb.rulenode.default-ttl + + + help + + + {{ 'tb.rulenode.default-ttl-required' | translate }} + + + {{ 'tb.rulenode.min-default-ttl-message' | translate }} + + +
    +
    + + {{ 'tb.rulenode.use-server-ts' | translate }} + +
    +
    + + {{ 'tb.rulenode.skip-latest-persistence' | translate }} + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.ts new file mode 100644 index 0000000000..d480ec4d39 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/timeseries-config.component.ts @@ -0,0 +1,45 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-timeseries-config', + templateUrl: './timeseries-config.component.html', + styleUrls: [] +}) +export class TimeseriesConfigComponent extends RuleNodeConfigurationComponent { + + timeseriesConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.timeseriesConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.timeseriesConfigForm = this.fb.group({ + defaultTTL: [configuration ? configuration.defaultTTL : null, [Validators.required, Validators.min(0)]], + skipLatestPersistence: [configuration ? configuration.skipLatestPersistence : false, []], + useServerTs: [configuration ? configuration.useServerTs : false, []] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.html new file mode 100644 index 0000000000..94d2447d19 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.html @@ -0,0 +1,39 @@ + +
    +
    + +
    +
    + + {{ 'tb.rulenode.unassign-from-customer' | translate }} + +
    + + tb.rulenode.customer-name-pattern + + + {{ 'tb.rulenode.customer-name-pattern-required' | translate }} + + tb.rulenode.customer-name-pattern-hint + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.ts new file mode 100644 index 0000000000..a514a5b495 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/unassign-customer-config.component.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 { Component } from '@angular/core'; +import { isDefinedAndNotNull } from '@core/public-api'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-un-assign-to-customer-config', + templateUrl: './unassign-customer-config.component.html', + styleUrls: [] +}) +export class UnassignCustomerConfigComponent extends RuleNodeConfigurationComponent { + + unassignCustomerConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.unassignCustomerConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + customerNamePattern: isDefinedAndNotNull(configuration?.customerNamePattern) ? configuration.customerNamePattern : null, + unassignFromCustomer: isDefinedAndNotNull(configuration?.customerNamePattern), + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.unassignCustomerConfigForm = this.fb.group({ + customerNamePattern: [configuration.customerNamePattern , []], + unassignFromCustomer: [configuration.unassignFromCustomer, []] + }); + } + + protected validatorTriggers(): string[] { + return ['unassignFromCustomer']; + } + + protected updateValidators(emitEvent: boolean) { + const unassignFromCustomer: boolean = this.unassignCustomerConfigForm.get('unassignFromCustomer').value; + if (unassignFromCustomer) { + this.unassignCustomerConfigForm.get('customerNamePattern').setValidators([Validators.required, Validators.pattern(/.*\S.*/)]); + } else { + this.unassignCustomerConfigForm.get('customerNamePattern').setValidators([]); + } + this.unassignCustomerConfigForm.get('customerNamePattern').updateValueAndValidity({emitEvent}); + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + customerNamePattern: configuration.unassignFromCustomer ? configuration.customerNamePattern.trim() : null + }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.html new file mode 100644 index 0000000000..3406218f10 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.html @@ -0,0 +1,37 @@ + +
    + +
    + + {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_UNACK) | translate }} + + + {{ alarmStatusTranslations.get(alarmStatus.ACTIVE_ACK) | translate }} + +
    +
    + + {{ alarmStatusTranslations.get(alarmStatus.CLEARED_UNACK) | translate }} + + + {{ alarmStatusTranslations.get(alarmStatus.CLEARED_ACK) | translate }} + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.scss new file mode 100644 index 0000000000..4eca381bff --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.scss @@ -0,0 +1,60 @@ +/** + * 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 { + .chip-listbox { + max-width: 460px; + width: 100%; + + .toggle-column { + display: flex; + flex: 1 1 100%; + gap: 8px; + } + + .option { + margin: 0; + } + } + + @media screen and (max-width: 959px) { + .chip-listbox { + max-width: 360px; + + .toggle-column { + flex-direction: column; + } + } + } +} + +:host ::ng-deep { + .chip-listbox { + .mdc-evolution-chip-set__chips { + gap: 8px; + } + + .option { + button { + flex-basis: 100%; + justify-content: start; + } + + .mdc-evolution-chip__graphic { + flex-grow: 0; + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts new file mode 100644 index 0000000000..923a4f13fc --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts @@ -0,0 +1,83 @@ +/// +/// 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, OnDestroy, OnInit } from '@angular/core'; +import { AlarmStatus, alarmStatusTranslations, PageComponent } from '@shared/public-api'; +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; + +@Component({ + selector: 'tb-alarm-status-select', + templateUrl: './alarm-status-select.component.html', + styleUrls: ['./alarm-status-select.component.scss'], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => AlarmStatusSelectComponent), + multi: true + }] +}) + +export class AlarmStatusSelectComponent extends PageComponent implements OnInit, ControlValueAccessor, OnDestroy { + + public alarmStatusGroup: FormGroup; + + private propagateChange = null; + private destroy$ = new Subject(); + + readonly alarmStatus = AlarmStatus; + readonly alarmStatusTranslations = alarmStatusTranslations; + + constructor(private fb: FormBuilder) { + super(); + } + + ngOnInit(): void { + this.alarmStatusGroup = this.fb.group({ + alarmStatus: [null, []] + }); + + this.alarmStatusGroup.get('alarmStatus').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + this.propagateChange(value); + }); + } + + setDisabledState(isDisabled: boolean): void { + if (isDisabled) { + this.alarmStatusGroup.disable({emitEvent: false}); + } else { + this.alarmStatusGroup.enable({emitEvent: false}); + } + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + + writeValue(value: Array): void { + this.alarmStatusGroup.get('alarmStatus').patchValue(value, {emitEvent: false}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.html new file mode 100644 index 0000000000..e19a8a1408 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.html @@ -0,0 +1,129 @@ + +
    + +
    + + +
    + +
    + {{argumentControl.get('name').value}}. +
    + + tb.rulenode.argument-source-field-input + + + {{ argumentTypeMap.get(argumentControl.get('type').value)?.name | translate }} + + + {{ argumentTypeMap.get(argument).name | translate }} + + {{ argumentTypeMap.get(argument).description }} + + + + + tb.rulenode.argument-source-field-input-required + + +
    + + tb.rulenode.argument-key-field-input + + + help + + + tb.rulenode.argument-key-field-input-required + + + + tb.rulenode.constant-value-field-input + + + tb.rulenode.constant-value-field-input-required + + + + tb.rulenode.default-value-field-input + + +
    + + tb.rulenode.attribute-scope-field-input + + + {{ attributeScopeMap.get(scope) | translate }} + + + + tb.rulenode.attribute-scope-field-input-required + + +
    + +
    +
    +
    +
    +
    +
    + tb.rulenode.no-arguments-prompt +
    + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.scss new file mode 100644 index 0000000000..9f6893b5df --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.scss @@ -0,0 +1,27 @@ +/** + * 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 { + .mat-mdc-list-item.tb-argument { + border: solid rgba(0, 0, 0, .25) 1px; + border-radius: 4px; + padding: 10px 0; + margin-bottom: 16px; + } + + .arguments-list { + padding: 0px; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts new file mode 100644 index 0000000000..3b2e99cf96 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts @@ -0,0 +1,242 @@ +/// +/// 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, OnDestroy, OnInit } from '@angular/core'; +import { + ControlValueAccessor, + FormArray, + FormBuilder, + FormControl, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + Validator, + Validators +} from '@angular/forms'; +import { PageComponent } from '@shared/public-api'; +import { Subscription } from 'rxjs'; +import { CdkDragDrop } from '@angular/cdk/drag-drop'; +import { + ArgumentName, + ArgumentType, + ArgumentTypeMap, + AttributeScope, + AttributeScopeMap, + MathFunction, + MathFunctionMap +} from './../rule-node-config.models'; + +@Component({ + selector: 'tb-arguments-map-config', + templateUrl: './arguments-map-config.component.html', + styleUrls: ['./arguments-map-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ArgumentsMapConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ArgumentsMapConfigComponent), + multi: true, + } + ] +}) +export class ArgumentsMapConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, OnDestroy, Validator { + + @Input() disabled: boolean; + + private functionValue: MathFunction; + + get function(): MathFunction { + return this.functionValue; + } + + @Input() + set function(funcName: MathFunction) { + if (funcName && this.functionValue !== funcName) { + this.functionValue = funcName; + this.setupArgumentsFormGroup(true); + } + } + + maxArgs = 16; + minArgs = 1; + displayArgumentName = false; + + mathFunctionMap = MathFunctionMap; + ArgumentType = ArgumentType; + + argumentsFormGroup: FormGroup; + + attributeScopeMap = AttributeScopeMap; + argumentTypeMap = ArgumentTypeMap; + arguments = Object.values(ArgumentType); + attributeScope = Object.values(AttributeScope); + + private propagateChange = null; + + private valueChangeSubscription: Subscription[] = []; + + constructor(private fb: FormBuilder) { + super(); + } + + ngOnInit(): void { + this.argumentsFormGroup = this.fb.group({ + arguments: this.fb.array([]) + }); + + this.valueChangeSubscription.push(this.argumentsFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + })); + + this.setupArgumentsFormGroup(); + } + + public onDrop(event: CdkDragDrop) { + const columnsFormArray = this.argumentsFormArray; + const columnForm = columnsFormArray.at(event.previousIndex); + columnsFormArray.removeAt(event.previousIndex); + columnsFormArray.insert(event.currentIndex, columnForm); + this.updateArgumentNames(); + } + + get argumentsFormArray(): FormArray { + return this.argumentsFormGroup.get('arguments') as FormArray; + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.argumentsFormGroup.disable({emitEvent: false}); + } else { + this.argumentsFormGroup.enable({emitEvent: false}); + this.argumentsFormArray.controls + .forEach((control: FormGroup) => this.updateArgumentControlValidators(control)); + } + } + + ngOnDestroy() { + if (this.valueChangeSubscription.length) { + this.valueChangeSubscription.forEach(sub => sub.unsubscribe()); + } + } + + writeValue(argumentsList): void { + const argumentsControls: Array = []; + if (argumentsList) { + argumentsList.forEach((property, index) => { + argumentsControls.push(this.createArgumentControl(property, index)); + }); + } + this.argumentsFormGroup.setControl('arguments', this.fb.array(argumentsControls), {emitEvent: false}); + this.setupArgumentsFormGroup(); + } + + + public removeArgument(index: number) { + this.argumentsFormArray.removeAt(index); + this.updateArgumentNames(); + } + + public addArgument(emitEvent = true) { + const argumentsFormArray = this.argumentsFormArray; + const argumentControl = this.createArgumentControl(null, argumentsFormArray.length); + argumentsFormArray.push(argumentControl, {emitEvent}); + } + + public validate(c: FormControl) { + if (!this.argumentsFormGroup.valid) { + return { + argumentsRequired: true + }; + } + return null; + } + + private setupArgumentsFormGroup(emitEvent = false) { + if (this.function) { + this.maxArgs = this.mathFunctionMap.get(this.function).maxArgs; + this.minArgs = this.mathFunctionMap.get(this.function).minArgs; + this.displayArgumentName = this.function === MathFunction.CUSTOM; + } + if (this.argumentsFormGroup) { + this.argumentsFormGroup.get('arguments').setValidators([Validators.minLength(this.minArgs), Validators.maxLength(this.maxArgs)]); + while (this.argumentsFormArray.length > this.maxArgs) { + this.removeArgument(this.maxArgs - 1); + } + while (this.argumentsFormArray.length < this.minArgs) { + this.addArgument(emitEvent); + } + this.argumentsFormGroup.get('arguments').updateValueAndValidity({emitEvent: false}); + } + } + + private createArgumentControl(property: any, index: number): FormGroup { + const argumentControl = this.fb.group({ + type: [property?.type, [Validators.required]], + key: [property?.key, [Validators.required]], + name: [ArgumentName[index], [Validators.required]], + attributeScope: [property?.attributeScope ?? AttributeScope.SERVER_SCOPE, [Validators.required]], + defaultValue: [property?.defaultValue ? property?.defaultValue : null] + }); + this.updateArgumentControlValidators(argumentControl); + this.valueChangeSubscription.push(argumentControl.get('type').valueChanges.subscribe(() => { + this.updateArgumentControlValidators(argumentControl); + argumentControl.get('attributeScope').updateValueAndValidity({emitEvent: false}); + argumentControl.get('defaultValue').updateValueAndValidity({emitEvent: false}); + })); + return argumentControl; + } + + private updateArgumentControlValidators(control: FormGroup) { + const argumentType: ArgumentType = control.get('type').value; + if (argumentType === ArgumentType.ATTRIBUTE) { + control.get('attributeScope').enable({emitEvent: false}); + } else { + control.get('attributeScope').disable({emitEvent: false}); + } + if (argumentType && argumentType !== ArgumentType.CONSTANT) { + control.get('defaultValue').enable({emitEvent: false}); + } else { + control.get('defaultValue').disable({emitEvent: false}); + } + } + + private updateArgumentNames() { + this.argumentsFormArray.controls.forEach((argumentControl, argumentIndex) => { + argumentControl.get('name').setValue(ArgumentName[argumentIndex]); + }); + } + + private updateModel() { + const argumentsForm = this.argumentsFormArray.value; + if (!argumentsForm.length || !this.argumentsFormGroup.valid) { + this.propagateChange(null); + } else { + this.propagateChange(argumentsForm); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.html new file mode 100644 index 0000000000..ab51ee901c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.html @@ -0,0 +1,95 @@ + +
    + + + tb.rulenode.credentials + + {{ credentialsTypeTranslationsMap.get(credentialsConfigFormGroup.get('type').value) | translate }} + + + + + tb.rulenode.credentials-type + + + {{ credentialsTypeTranslationsMap.get(credentialsType) | translate }} + + + + {{ 'tb.rulenode.credentials-type-required' | translate }} + + +
    + + + + + tb.rulenode.username + + + {{ 'tb.rulenode.username-required' | translate }} + + + + tb.rulenode.password + + + + {{ 'tb.rulenode.password-required' | translate }} + + + + +
    {{ 'tb.rulenode.credentials-pem-hint' | translate }}
    + + + + + + + + tb.rulenode.private-key-password + + + +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts new file mode 100644 index 0000000000..97f0ba0846 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts @@ -0,0 +1,252 @@ +/// +/// 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, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; +import { + ControlValueAccessor, + FormBuilder, + FormControl, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + ValidationErrors, + Validator, + ValidatorFn, + Validators +} from '@angular/forms'; +import { AppState, isDefinedAndNotNull } from '@core/public-api'; +import { PageComponent } from '@shared/public-api'; +import { Store } from '@ngrx/store'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; +import { credentialsType, credentialsTypes, credentialsTypeTranslations } from '../rule-node-config.models'; +import { Subscription } from 'rxjs'; + +interface CredentialsConfig { + type: credentialsType; + username?: string; + password?: string; + caCert?: string; + caCertFileName?: string; + privateKey?: string; + privateKeyFileName?: string; + cert?: string; + certFileName?: string; +} + +@Component({ + selector: 'tb-credentials-config', + templateUrl: './credentials-config.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CredentialsConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => CredentialsConfigComponent), + multi: true, + } + ] +}) +export class CredentialsConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy, OnChanges { + + credentialsConfigFormGroup: FormGroup; + + subscriptions: Subscription[] = []; + + private requiredValue: boolean; + + get required(): boolean { + return this.requiredValue; + } + + @Input() + set required(value: boolean) { + this.requiredValue = coerceBooleanProperty(value); + } + + @Input() + disableCertPemCredentials = false; + + @Input() + passwordFieldRequired = true; + + allCredentialsTypes = credentialsTypes; + credentialsTypeTranslationsMap = credentialsTypeTranslations; + + private propagateChange = (_: any) => {}; + + constructor(protected store: Store, + private fb: FormBuilder) { + super(store); + } + + ngOnInit(): void { + this.credentialsConfigFormGroup = this.fb.group( + { + type: [null, [Validators.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(changes: SimpleChanges): void { + for (const propName of Object.keys(changes)) { + const change = changes[propName]; + if (!change.firstChange && change.currentValue !== change.previousValue) { + if (change.currentValue && propName === 'disableCertPemCredentials') { + const credentialsTypeValue: credentialsType = this.credentialsConfigFormGroup.get('type').value; + if (credentialsTypeValue === 'cert.PEM') { + setTimeout(() => { + this.credentialsConfigFormGroup.get('type').patchValue('anonymous', {emitEvent: true}); + }); + } + } + } + } + } + + ngOnDestroy() { + this.subscriptions.forEach(s => s.unsubscribe()); + } + + writeValue(credentials: CredentialsConfig | null): void { + if (isDefinedAndNotNull(credentials)) { + this.credentialsConfigFormGroup.reset(credentials, {emitEvent: false}); + this.updateValidators(); + } + } + + setDisabledState(isDisabled: boolean): void { + if (isDisabled) { + this.credentialsConfigFormGroup.disable({emitEvent: false}); + } else { + this.credentialsConfigFormGroup.enable({emitEvent: false}); + this.updateValidators(); + } + } + + updateView() { + let credentialsConfigValue = this.credentialsConfigFormGroup.value; + const credentialsTypeValue: credentialsType = credentialsConfigValue.type; + switch (credentialsTypeValue) { + case 'anonymous': + credentialsConfigValue = { + type: credentialsTypeValue + }; + break; + case 'basic': + credentialsConfigValue = { + type: credentialsTypeValue, + username: credentialsConfigValue.username, + password: credentialsConfigValue.password, + }; + break; + case 'cert.PEM': + delete credentialsConfigValue.username; + break; + } + this.propagateChange(credentialsConfigValue); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + public validate(c: FormControl) { + return this.credentialsConfigFormGroup.valid ? null : { + credentialsConfig: { + valid: false, + }, + }; + } + + credentialsTypeChanged(): void { + this.credentialsConfigFormGroup.patchValue({ + username: null, + password: null, + caCert: null, + caCertFileName: null, + privateKey: null, + privateKeyFileName: null, + cert: null, + certFileName: null, + }); + this.updateValidators(); + } + + protected updateValidators(emitEvent: boolean = false) { + const credentialsTypeValue: credentialsType = this.credentialsConfigFormGroup.get('type').value; + if (emitEvent) { + this.credentialsConfigFormGroup.reset({type: credentialsTypeValue}, {emitEvent: false}); + } + this.credentialsConfigFormGroup.setValidators([]); + this.credentialsConfigFormGroup.get('username').setValidators([]); + this.credentialsConfigFormGroup.get('password').setValidators([]); + switch (credentialsTypeValue) { + case 'anonymous': + break; + case 'basic': + this.credentialsConfigFormGroup.get('username').setValidators([Validators.required]); + this.credentialsConfigFormGroup.get('password').setValidators(this.passwordFieldRequired ? [Validators.required] : []); + break; + case 'cert.PEM': + this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected( + Validators.required, + [['caCert', 'caCertFileName'], ['privateKey', 'privateKeyFileName', 'cert', 'certFileName']] + )]); + break; + } + this.credentialsConfigFormGroup.get('username').updateValueAndValidity({emitEvent}); + this.credentialsConfigFormGroup.get('password').updateValueAndValidity({emitEvent}); + this.credentialsConfigFormGroup.updateValueAndValidity({emitEvent}); + } + + private requiredFilesSelected(validator: ValidatorFn, + requiredFieldsSet: string[][] = null) { + return (group: FormGroup): ValidationErrors | null => { + if (!requiredFieldsSet) { + requiredFieldsSet = [Object.keys(group.controls)]; + } + const allRequiredFilesSelected = group?.controls && + requiredFieldsSet.some(arrFields => arrFields.every(k => !validator(group.controls[k]))); + + return allRequiredFilesSelected ? null : {notAllRequiredFilesSelected: true}; + }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.html new file mode 100644 index 0000000000..56d8c948d9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.html @@ -0,0 +1,66 @@ + +
    +
    + + relation.direction + + + {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix + + + + + tb.rulenode.max-relation-level + + + {{ 'tb.rulenode.max-relation-level-error' | translate }} + + + {{ 'tb.rulenode.max-relation-level-invalid' | translate }} + + +
    +
    + + {{ 'alias.last-level-relation' | translate }} + +
    + + + + help + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.scss new file mode 100644 index 0000000000..95cfd96f20 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.scss @@ -0,0 +1,20 @@ +/** + * 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 { + .last-level-slide-toggle { + margin: 8px 0 24px; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts new file mode 100644 index 0000000000..23aee0b29a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts @@ -0,0 +1,108 @@ +/// +/// 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, OnInit } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; +import { PageComponent } from '@shared/components/page.component'; +import { EntitySearchDirection, entitySearchDirectionTranslations } from '@app/shared/models/relation.models'; +import { EntityType } from '@shared/models/entity-type.models'; + +interface DeviceRelationsQuery { + fetchLastLevelOnly: boolean; + direction: EntitySearchDirection; + maxLevel?: number; + relationType?: string; + deviceTypes: string[]; +} + +@Component({ + selector: 'tb-device-relations-query-config', + templateUrl: './device-relations-query-config.component.html', + styleUrls: ['./device-relations-query-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => DeviceRelationsQueryConfigComponent), + multi: true + } + ] +}) +export class DeviceRelationsQueryConfigComponent extends PageComponent implements ControlValueAccessor, OnInit { + + @Input() disabled: boolean; + + private requiredValue: boolean; + + get required(): boolean { + return this.requiredValue; + } + + @Input() + set required(value: boolean) { + this.requiredValue = coerceBooleanProperty(value); + } + + directionTypes: Array = Object.values(EntitySearchDirection); + directionTypeTranslations = entitySearchDirectionTranslations; + + entityType = EntityType; + + deviceRelationsQueryFormGroup: FormGroup; + + private propagateChange = null; + + constructor(private fb: FormBuilder) { + super(); + } + + ngOnInit(): void { + this.deviceRelationsQueryFormGroup = this.fb.group({ + fetchLastLevelOnly: [false, []], + direction: [null, [Validators.required]], + maxLevel: [null, [Validators.min(1)]], + relationType: [null], + deviceTypes: [null, [Validators.required]] + }); + this.deviceRelationsQueryFormGroup.valueChanges.subscribe((query: DeviceRelationsQuery) => { + if (this.deviceRelationsQueryFormGroup.valid) { + this.propagateChange(query); + } else { + this.propagateChange(null); + } + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.deviceRelationsQueryFormGroup.disable({emitEvent: false}); + } else { + this.deviceRelationsQueryFormGroup.enable({emitEvent: false}); + } + } + + writeValue(query: DeviceRelationsQuery): void { + this.deviceRelationsQueryFormGroup.reset(query, {emitEvent: false}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.html new file mode 100644 index 0000000000..b10c9f16b8 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.html @@ -0,0 +1,29 @@ + +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.scss new file mode 100644 index 0000000000..da530c0540 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.scss @@ -0,0 +1,31 @@ +/** + * 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 { + .space-between { + display: flex; + justify-content: space-between; + gap: 20px; + + .see-example { + display: flex; + flex-shrink: 0; + } + } + + .hint-text { + width: 100%; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.ts new file mode 100644 index 0000000000..98c537fa0e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.ts @@ -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 { Component, Input } from '@angular/core'; + +@Component({ + selector: 'tb-example-hint', + templateUrl: './example-hint.component.html', + styleUrls: ['./example-hint.component.scss'] +}) +export class ExampleHintComponent { + @Input() hintText: string; + + @Input() popupHelpLink: string; + + @Input() textAlign: string = 'left'; +} + + diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html new file mode 100644 index 0000000000..761b9c9491 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html @@ -0,0 +1,70 @@ + +
    +
    + {{ keyText | translate }} + {{ valText | translate }} + +
    +
    +
    + + + + {{ keyRequiredText | translate }} + + + + + + {{ valRequiredText | translate }} + + + +
    +
    +
    + +
    + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.scss new file mode 100644 index 0000000000..fad3641ba4 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.scss @@ -0,0 +1,59 @@ +/** + * 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 { + .tb-kv-map-config { + margin-bottom: 16px; + + .header { + padding-left: 5px; + padding-right: 5px; + padding-bottom: 5px; + + .cell { + padding-left: 5px; + padding-right: 5px; + color: #757575; + font-size: 12px; + font-weight: 700; + white-space: nowrap; + } + + .tb-required::after { + color: #757575; + font-size: 12px; + font-weight: 700; + } + } + + .body { + padding-left: 5px; + padding-right: 5px; + padding-bottom: 0; + max-height: 300px; + overflow: auto; + + .cell { + padding-left: 5px; + padding-right: 5px; + } + } + + tb-error { + display: block; + margin-top: -12px; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts new file mode 100644 index 0000000000..a08394479a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts @@ -0,0 +1,198 @@ +/// +/// 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, Injector, Input, OnInit } from '@angular/core'; +import { + AbstractControl, + ControlValueAccessor, + FormArray, + FormBuilder, + FormControl, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + NgControl, + Validator, + Validators +} from '@angular/forms'; +import { PageComponent } from '@shared/public-api'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/public-api'; +import { Subscription } from 'rxjs'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; +import { TranslateService } from '@ngx-translate/core'; + +@Component({ + selector: 'tb-kv-map-config-old', + templateUrl: './kv-map-config-old.component.html', + styleUrls: ['./kv-map-config-old.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => KvMapConfigOldComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => KvMapConfigOldComponent), + multi: true, + } + ] +}) +export class KvMapConfigOldComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator { + + @Input() disabled: boolean; + + @Input() uniqueKeyValuePairValidator: boolean; + + @Input() requiredText: string; + + @Input() keyText: string; + + @Input() keyRequiredText: string; + + @Input() valText: string; + + @Input() valRequiredText: string; + + @Input() hintText: string; + + private requiredValue: boolean; + + get required(): boolean { + return this.requiredValue; + } + + @Input() + set required(value: boolean) { + this.requiredValue = coerceBooleanProperty(value); + } + + kvListFormGroup: FormGroup; + + ngControl: NgControl; + + private propagateChange = null; + + private valueChangeSubscription: Subscription = null; + + constructor(protected store: Store, + public translate: TranslateService, + public injector: Injector, + private fb: FormBuilder) { + super(store); + } + + ngOnInit(): void { + this.ngControl = this.injector.get(NgControl); + if (this.ngControl != null) { + this.ngControl.valueAccessor = this; + } + this.kvListFormGroup = this.fb.group({}); + this.kvListFormGroup.addControl('keyVals', + this.fb.array([])); + } + + keyValsFormArray(): FormArray { + return this.kvListFormGroup.get('keyVals') as FormArray; + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.kvListFormGroup.disable({emitEvent: false}); + } else { + this.kvListFormGroup.enable({emitEvent: false}); + } + } + + writeValue(keyValMap: { [key: string]: string }): void { + if (this.valueChangeSubscription) { + this.valueChangeSubscription.unsubscribe(); + } + const keyValsControls: Array = []; + if (keyValMap) { + for (const property of Object.keys(keyValMap)) { + if (Object.prototype.hasOwnProperty.call(keyValMap, property)) { + keyValsControls.push(this.fb.group({ + key: [property, [Validators.required]], + value: [keyValMap[property], [Validators.required]] + })); + } + } + } + this.kvListFormGroup.setControl('keyVals', this.fb.array(keyValsControls)); + this.valueChangeSubscription = this.kvListFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + }); + } + + public removeKeyVal(index: number) { + (this.kvListFormGroup.get('keyVals') as FormArray).removeAt(index); + } + + public addKeyVal() { + const keyValsFormArray = this.kvListFormGroup.get('keyVals') as FormArray; + keyValsFormArray.push(this.fb.group({ + key: ['', [Validators.required]], + value: ['', [Validators.required]] + })); + } + + public validate(c: FormControl) { + const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; + if (!kvList.length && this.required) { + return { + kvMapRequired: true + }; + } + if (!this.kvListFormGroup.valid) { + return { + kvFieldsRequired: true + }; + } + if (this.uniqueKeyValuePairValidator) { + for (const kv of kvList) { + if (kv.key === kv.value) { + return { + uniqueKeyValuePair: true + }; + } + } + } + return null; + } + + private updateModel() { + const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; + if (this.required && !kvList.length || !this.kvListFormGroup.valid) { + this.propagateChange(null); + } else { + const keyValMap: { [key: string]: string } = {}; + kvList.forEach((entry) => { + keyValMap[entry.key] = entry.value; + }); + this.propagateChange(keyValMap); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.html new file mode 100644 index 0000000000..36945c2211 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.html @@ -0,0 +1,72 @@ + +
    +
    +
    {{ labelText }}
    +
    + {{ requiredText }} +
    +
    + tb.rulenode.map-fields-required +
    +
    + {{ 'tb.key-val.unique-key-value-pair-error' | translate: + { + valText: valText, + keyText: keyText + } }} +
    +
    +
    +
    +
    +
    {{ keyText }}
    +
    {{ valText }}
    +
    +
    +
    +
    + + + + + + +
    + +
    +
    +
    +
    +
    +
    + +
    + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.scss new file mode 100644 index 0000000000..132a1f882c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.scss @@ -0,0 +1,24 @@ +/** + * 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 { + .field-space { + flex: 1 1 50%; + } + + .actions-header { + width: 40px + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts new file mode 100644 index 0000000000..042dcf94bd --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts @@ -0,0 +1,240 @@ +/// +/// 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, Injector, Input, OnDestroy, OnInit } from '@angular/core'; +import { + AbstractControl, + ControlValueAccessor, + FormArray, + FormBuilder, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + NgControl, + ValidationErrors, + Validator, + ValidatorFn, + Validators +} from '@angular/forms'; +import { coerceBoolean } from '@shared/public-api'; +import { isEqual } from '@core/public-api'; +import { Subject, takeUntil } from 'rxjs'; + +@Component({ + selector: 'tb-kv-map-config', + templateUrl: './kv-map-config.component.html', + styleUrls: ['./kv-map-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => KvMapConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => KvMapConfigComponent), + multi: true, + } + ] +}) +export class KvMapConfigComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy { + + private propagateChange: (value: any) => void = () => {}; + private destroy$ = new Subject(); + + kvListFormGroup: FormGroup; + ngControl: NgControl; + + @Input() + @coerceBoolean() + disabled = false; + + @Input() + @coerceBoolean() + uniqueKeyValuePairValidator = false; + + @Input() labelText: string; + + @Input() requiredText: string; + + @Input() keyText: string; + + @Input() keyRequiredText: string; + + @Input() valText: string; + + @Input() valRequiredText: string; + + @Input() hintText: string; + + @Input() popupHelpLink: string; + + @Input() + @coerceBoolean() + required = false; + + constructor(private injector: Injector, + private fb: FormBuilder) { + } + + ngOnInit(): void { + this.ngControl = this.injector.get(NgControl); + if (this.ngControl != null) { + this.ngControl.valueAccessor = this; + } + + this.kvListFormGroup = this.fb.group({ + keyVals: this.fb.array([]) + }, {validators: [this.propagateNestedErrors, this.oneMapRequiredValidator]}); + + this.kvListFormGroup.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(() => { + this.updateModel(); + }); + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + + keyValsFormArray(): FormArray { + return this.kvListFormGroup.get('keyVals') as FormArray; + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.kvListFormGroup.disable({emitEvent: false}); + } else { + this.kvListFormGroup.enable({emitEvent: false}); + } + } + + private duplicateValuesValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => + control.controls.key.value === control.controls.value.value + ? control.controls.key.value && control.controls.value.value ? { uniqueKeyValuePair: true } : null + : null; + + private oneMapRequiredValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => control.get('keyVals').value.length; + + + private propagateNestedErrors: ValidatorFn = (controls: FormArray | FormGroup | AbstractControl): ValidationErrors | null => { + if (this.kvListFormGroup && this.kvListFormGroup.get('keyVals') && this.kvListFormGroup.get('keyVals')?.status === 'VALID') { + return null; + } + const errors = {}; + if (this.kvListFormGroup) { + this.kvListFormGroup.setErrors(null); + } + if (controls instanceof FormArray || controls instanceof FormGroup) { + if (controls.errors) { + for (const errorKey of Object.keys(controls.errors)) { + errors[errorKey] = true; + } + } + for (const control of Object.keys(controls.controls)) { + const innerErrors = this.propagateNestedErrors(controls.controls[control]); + if (innerErrors && Object.keys(innerErrors).length) { + for (const errorKey of Object.keys(innerErrors)) { + errors[errorKey] = true; + } + } + } + return errors; + } else { + if (controls.errors) { + for (const errorKey of Object.keys(controls.errors)) { + errors[errorKey] = true; + } + } + } + + return !isEqual(errors, {}) ? errors : null; + }; + + writeValue(keyValMap: { [key: string]: string }): void { + const keyValuesData = Object.keys(keyValMap).map(key => ({key, value: keyValMap[key]})); + if (this.keyValsFormArray().length === keyValuesData.length) { + this.keyValsFormArray().patchValue(keyValuesData, {emitEvent: false}); + } else { + const keyValsControls: Array = []; + keyValuesData.forEach(data => { + keyValsControls.push(this.fb.group({ + key: [data.key, [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]], + value: [data.value, [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]] + }, {validators: this.uniqueKeyValuePairValidator ? [this.duplicateValuesValidator] : []})); + }); + this.kvListFormGroup.setControl('keyVals', this.fb.array(keyValsControls, this.propagateNestedErrors), {emitEvent: false}); + } + } + + public removeKeyVal(index: number) { + this.keyValsFormArray().removeAt(index); + } + + public addKeyVal() { + this.keyValsFormArray().push(this.fb.group({ + key: ['', [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]], + value: ['', [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]] + }, {validators: this.uniqueKeyValuePairValidator ? [this.duplicateValuesValidator] : []})); + } + + public validate() { + const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; + if (!kvList.length && this.required) { + return { + kvMapRequired: true + }; + } + if (!this.kvListFormGroup.valid) { + return { + kvFieldsRequired: true + }; + } + if (this.uniqueKeyValuePairValidator) { + for (const kv of kvList) { + if (kv.key === kv.value) { + return { + uniqueKeyValuePair: true + }; + } + } + } + return null; + } + + private updateModel() { + const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; + if (this.required && !kvList.length || !this.kvListFormGroup.valid) { + this.propagateChange(null); + } else { + const keyValMap: { [key: string]: string } = {}; + kvList.forEach((entry) => { + keyValMap[entry.key] = entry.value; + }); + this.propagateChange(keyValMap); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.html new file mode 100644 index 0000000000..6a2bf514ad --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.html @@ -0,0 +1,43 @@ + + + tb.rulenode.functions-field-input + + + + + + + {{ option.description }} + + + + tb.rulenode.no-option-found + + + diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts new file mode 100644 index 0000000000..1583048073 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts @@ -0,0 +1,152 @@ +/// +/// 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, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; +import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { Observable } from 'rxjs'; +import { TranslateService } from '@ngx-translate/core'; +import { FunctionData, MathFunction, MathFunctionMap } from '../rule-node-config.models'; +import { map, tap } from 'rxjs/operators'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; + +@Component({ + selector: 'tb-math-function-autocomplete', + templateUrl: './math-function-autocomplete.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MathFunctionAutocompleteComponent), + multi: true + } + ] +}) +export class MathFunctionAutocompleteComponent implements ControlValueAccessor, OnInit { + + private requiredValue: boolean; + + get required(): boolean { + return this.requiredValue; + } + + @Input() + set required(value: boolean) { + this.requiredValue = coerceBooleanProperty(value); + } + + @Input() disabled: boolean; + + @ViewChild('operationInput', {static: true}) operationInput: ElementRef; + + mathFunctionForm: UntypedFormGroup; + + modelValue: MathFunction | null; + + searchText = ''; + + filteredOptions: Observable; + + private dirty = false; + + private mathOperation = [...MathFunctionMap.values()]; + + private propagateChange = null; + + constructor(public translate: TranslateService, + private fb: UntypedFormBuilder) { + } + + ngOnInit(): void { + this.mathFunctionForm = this.fb.group({ + operation: [''] + }); + this.filteredOptions = this.mathFunctionForm.get('operation').valueChanges.pipe( + tap(value => { + let modelValue; + if (typeof value === 'string' && MathFunction[value]) { + modelValue = MathFunction[value]; + } else { + modelValue = null; + } + this.updateView(modelValue); + }), + map(value => { + this.searchText = value || ''; + return value ? this._filter(value) : this.mathOperation.slice(); + }), + ); + } + + private _filter(searchText: string) { + const filterValue = searchText.toLowerCase(); + + return this.mathOperation.filter(option => option.name.toLowerCase().includes(filterValue) + || option.value.toLowerCase().includes(filterValue)); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.mathFunctionForm.disable({emitEvent: false}); + } else { + this.mathFunctionForm.enable({emitEvent: false}); + } + } + + mathFunctionDisplayFn(value: MathFunction | null) { + if (value) { + const funcData = MathFunctionMap.get(value) + return funcData.value + ' | ' + funcData.name; + } + return ''; + } + + writeValue(value: MathFunction | null): void { + this.modelValue = value; + this.mathFunctionForm.get('operation').setValue(value, {emitEvent: false}); + this.dirty = true; + } + + updateView(value: MathFunction | null) { + if (this.modelValue !== value) { + this.modelValue = value; + this.propagateChange(this.modelValue); + } + } + + onFocus() { + if (this.dirty) { + this.mathFunctionForm.get('operation').updateValueAndValidity({onlySelf: true}); + this.dirty = false; + } + } + + clear() { + this.mathFunctionForm.get('operation').patchValue(''); + setTimeout(() => { + this.operationInput.nativeElement.blur(); + this.operationInput.nativeElement.focus(); + }, 0); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.html new file mode 100644 index 0000000000..df52912735 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.html @@ -0,0 +1,71 @@ + + + {{ label }} + + + {{messageType.name}} + close + + + + + + + + +
    +
    + tb.rulenode.no-message-types-found +
    + + + {{ 'tb.rulenode.no-message-type-matching' | translate : + {messageType: truncate.transform(searchText, true, 6, '...')} + }} + + + + tb.rulenode.create-new-message-type + +
    +
    +
    + help + + {{ 'tb.rulenode.select-message-types-required' | translate }} + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts new file mode 100644 index 0000000000..278819cb80 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts @@ -0,0 +1,239 @@ +/// +/// 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, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; +import { LinkLabel, MessageType, messageTypeNames, PageComponent, TruncatePipe } from '@shared/public-api'; +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { MatChipGrid, MatChipInputEvent } from '@angular/material/chips'; +import { MatAutocomplete, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; +import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; +import { Observable, of } from 'rxjs'; +import { map, mergeMap, share, startWith } from 'rxjs/operators'; +import { TranslateService } from '@ngx-translate/core'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; + +@Component({ + selector: 'tb-message-types-config', + templateUrl: './message-types-config.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MessageTypesConfigComponent), + multi: true + } + ] +}) +export class MessageTypesConfigComponent extends PageComponent implements ControlValueAccessor, OnInit { + + messageTypeConfigForm: FormGroup; + + private requiredValue: boolean; + + get required(): boolean { + return this.requiredValue; + } + + @Input() + set required(value: boolean) { + this.requiredValue = coerceBooleanProperty(value); + } + + @Input() + label: string; + + @Input() + placeholder = 'tb.rulenode.add-message-type'; + + @Input() + disabled: boolean; + + @ViewChild('chipList', {static: false}) chipList: MatChipGrid; + @ViewChild('messageTypeAutocomplete', {static: false}) matAutocomplete: MatAutocomplete; + @ViewChild('messageTypeInput', {static: false}) messageTypeInput: ElementRef; + + separatorKeysCodes = [ENTER, COMMA, SEMICOLON]; + + filteredMessageTypes: Observable>; + + messageTypes: Array = []; + + private messageTypesList: Array = []; + + searchText = ''; + + private propagateChange = (v: any) => { }; + + constructor(public translate: TranslateService, + public truncate: TruncatePipe, + private fb: FormBuilder) { + super(); + this.messageTypeConfigForm = this.fb.group({ + messageType: [null] + }); + for (const type of Object.keys(MessageType)) { + this.messageTypesList.push( + { + name: messageTypeNames.get(MessageType[type]), + value: type + } + ); + } + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + ngOnInit() { + this.filteredMessageTypes = this.messageTypeConfigForm.get('messageType').valueChanges + .pipe( + startWith(''), + map((value) => value ? value : ''), + mergeMap(name => this.fetchMessageTypes(name)), + share() + ); + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.messageTypeConfigForm.disable({emitEvent: false}); + } else { + this.messageTypeConfigForm.enable({emitEvent: false}); + } + } + + writeValue(value: Array | null): void { + this.searchText = ''; + this.messageTypes.length = 0; + if (value) { + value.forEach((type: string) => { + const found = this.messageTypesList.find((messageType => messageType.value === type)); + if (found) { + this.messageTypes.push({ + name: found.name, + value: found.value + }); + } else { + this.messageTypes.push({ + name: type, + value: type + }); + } + }); + } + } + + displayMessageTypeFn(messageType?: LinkLabel): string | undefined { + return messageType ? messageType.name : undefined; + } + + textIsNotEmpty(text: string): boolean { + return text && text.length > 0; + } + + createMessageType($event: Event, value: string) { + $event.preventDefault(); + this.transformMessageType(value); + } + + add(event: MatChipInputEvent): void { + this.transformMessageType(event.value); + } + + private fetchMessageTypes(searchText?: string): Observable> { + this.searchText = searchText; + if (this.searchText && this.searchText.length) { + const search = this.searchText.toUpperCase(); + return of(this.messageTypesList.filter(messageType => messageType.name.toUpperCase().includes(search))); + } else { + return of(this.messageTypesList); + } + } + + private transformMessageType(value: string) { + if ((value || '').trim()) { + let newMessageType: LinkLabel; + const messageTypeName = value.trim(); + const existingMessageType = this.messageTypesList.find(messageType => messageType.name === messageTypeName); + if (existingMessageType) { + newMessageType = { + name: existingMessageType.name, + value: existingMessageType.value + }; + } else { + newMessageType = { + name: messageTypeName, + value: messageTypeName + }; + } + if (newMessageType) { + this.addMessageType(newMessageType); + } + } + this.clear(''); + } + + remove(messageType: LinkLabel) { + const index = this.messageTypes.indexOf(messageType); + if (index >= 0) { + this.messageTypes.splice(index, 1); + this.updateModel(); + } + } + + selected(event: MatAutocompleteSelectedEvent): void { + this.addMessageType(event.option.value); + this.clear(''); + } + + addMessageType(messageType: LinkLabel): void { + const index = this.messageTypes.findIndex(existingMessageType => existingMessageType.value === messageType.value); + if (index === -1) { + this.messageTypes.push(messageType); + this.updateModel(); + } + } + + onFocus() { + this.messageTypeConfigForm.get('messageType').updateValueAndValidity({onlySelf: true, emitEvent: true}); + } + + clear(value: string = '') { + this.messageTypeInput.nativeElement.value = value; + this.messageTypeConfigForm.get('messageType').patchValue(null, {emitEvent: true}); + setTimeout(() => { + this.messageTypeInput.nativeElement.blur(); + this.messageTypeInput.nativeElement.focus(); + }, 0); + } + + private updateModel() { + const value = this.messageTypes.map((messageType => messageType.value)); + if (this.required) { + this.chipList.errorState = !value.length; + this.propagateChange(value.length > 0 ? value : null); + } else { + this.chipList.errorState = false; + this.propagateChange(value); + } + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.html new file mode 100644 index 0000000000..d3fcba933c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.html @@ -0,0 +1,26 @@ + +
    +
    {{ labelText }}
    + + {{ option.name }} + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts new file mode 100644 index 0000000000..066cea455e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts @@ -0,0 +1,96 @@ +/// +/// 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, OnDestroy, OnInit } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { FetchTo, FetchToTranslation } from '../rule-node-config.models'; +import { takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; +import { TranslateService } from '@ngx-translate/core'; + +@Component({ + selector: 'tb-msg-metadata-chip', + templateUrl: './msg-metadata-chip.component.html', + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => MsgMetadataChipComponent), + multi: true + }] +}) + +export class MsgMetadataChipComponent implements OnInit, ControlValueAccessor, OnDestroy { + + @Input() labelText: string; + @Input() translation: Map = FetchToTranslation; + + private propagateChange: (value: any) => void = () => {}; + private destroy$ = new Subject(); + + public chipControlGroup: FormGroup; + public selectOptions = []; + + constructor(private fb: FormBuilder, + private translate: TranslateService) {} + + ngOnInit(): void { + this.initOptions(); + this.chipControlGroup = this.fb.group({ + chipControl: [null, []] + }); + + this.chipControlGroup.get('chipControl').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + if (value) { + this.propagateChange(value); + } + } + ); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + initOptions() { + for (const key of this.translation.keys()) { + this.selectOptions.push({ + value: key, + name: this.translate.instant(this.translation.get(key)) + }); + } + } + + writeValue(value: string | null): void { + this.chipControlGroup.get('chipControl').patchValue(value, {emitEvent: false}); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + if (isDisabled) { + this.chipControlGroup.disable({emitEvent: false}); + } else { + this.chipControlGroup.enable({emitEvent: false}); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.html new file mode 100644 index 0000000000..832c633d5d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.html @@ -0,0 +1,50 @@ + +
    + + {{'tb.rulenode.output-message-type' | translate}} + + + {{msgType.name}} + + + + + {{'tb.rulenode.message-type-value' | translate}} + + + + {{ 'tb.rulenode.message-type-value-required' | translate }} + + + {{ 'tb.rulenode.message-type-value-max-length' | translate }} + + +
    + diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts new file mode 100644 index 0000000000..494b686ba3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts @@ -0,0 +1,178 @@ +/// +/// 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, OnDestroy } from '@angular/core'; +import { + ControlValueAccessor, + FormBuilder, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + Validator, + Validators +} from '@angular/forms'; +import { SubscriptSizing } from '@angular/material/form-field'; +import { coerceBoolean } from '@shared/public-api'; +import { Subject, takeUntil } from 'rxjs'; + +interface MessageType { + name: string; + value: string; +} + +@Component({ + selector: 'tb-output-message-type-autocomplete', + templateUrl: './output-message-type-autocomplete.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => OutputMessageTypeAutocompleteComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => OutputMessageTypeAutocompleteComponent), + multi: true + } + ] +}) + +export class OutputMessageTypeAutocompleteComponent implements ControlValueAccessor, Validator, OnDestroy { + + @Input() + subscriptSizing: SubscriptSizing = 'fixed'; + + @Input() + @coerceBoolean() + disabled: boolean; + + @Input() + @coerceBoolean() + set required(value) { + if (this.requiredValue !== value) { + this.requiredValue = value; + this.updateValidators(); + } + } + + get required() { + return this.requiredValue; + } + + messageTypeFormGroup: FormGroup; + + messageTypes: MessageType[] = [ + { + name: 'Post attributes', + value: 'POST_ATTRIBUTES_REQUEST' + }, + { + name: 'Post telemetry', + value: 'POST_TELEMETRY_REQUEST' + }, + { + name: 'Custom', + value: '' + }, + ]; + + private modelValue: string | null; + private requiredValue: boolean; + private propagateChange: (value: any) => void = () => {}; + private destroy$ = new Subject(); + + constructor(private fb: FormBuilder) { + this.messageTypeFormGroup = this.fb.group({ + messageTypeAlias: [null, [Validators.required]], + messageType: [{value: null, disabled: true}, [Validators.maxLength(255)]] + }); + this.messageTypeFormGroup.get('messageTypeAlias').valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(value => this.updateMessageTypeValue(value)); + this.messageTypeFormGroup.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(() => this.updateView()); + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + + registerOnTouched(fn: any): void { + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + writeValue(value: string | null): void { + this.modelValue = value; + let findMessage = this.messageTypes.find(msgType => msgType.value === value); + if (!findMessage) { + findMessage = this.messageTypes.find(msgType => msgType.value === ''); + } + this.messageTypeFormGroup.get('messageTypeAlias').patchValue(findMessage, {emitEvent: false}); + this.messageTypeFormGroup.get('messageType').patchValue(value, {emitEvent: false}); + } + + validate() { + if (!this.messageTypeFormGroup.valid) { + return { + messageTypeInvalid: true + }; + } + return null; + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (isDisabled) { + this.messageTypeFormGroup.disable({emitEvent: false}); + } else { + this.messageTypeFormGroup.enable({emitEvent: false}); + if (this.messageTypeFormGroup.get('messageTypeAlias').value?.name !== 'Custom') { + this.messageTypeFormGroup.get('messageType').disable({emitEvent: false}); + } + } + } + + private updateView() { + const value = this.messageTypeFormGroup.getRawValue().messageType; + if (this.modelValue !== value) { + this.modelValue = value; + this.propagateChange(this.modelValue); + } + } + + private updateValidators() { + this.messageTypeFormGroup.get('messageType').setValidators( + this.required ? [Validators.required, Validators.maxLength(255)] : [Validators.maxLength(255)] + ); + this.messageTypeFormGroup.get('messageType').updateValueAndValidity({emitEvent: false}); + } + + private updateMessageTypeValue(choseMessageType: MessageType) { + if (choseMessageType?.name !== 'Custom') { + this.messageTypeFormGroup.get('messageType').disable({emitEvent: false}); + } else { + this.messageTypeFormGroup.get('messageType').enable({emitEvent: false}); + } + this.messageTypeFormGroup.get('messageType').patchValue(choseMessageType.value ?? null); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.html new file mode 100644 index 0000000000..d60e993e88 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.html @@ -0,0 +1,45 @@ + +
    + + {{ 'alias.last-level-relation' | translate }} + +
    + + relation.direction + + + {{ directionTypeTranslations.get(type) | translate }} + + + + + tb.rulenode.max-relation-level + + +
    +
    relation.relation-filters
    + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts new file mode 100644 index 0000000000..e89cd249f8 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts @@ -0,0 +1,99 @@ +/// +/// 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, OnInit } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; +import { EntitySearchDirection, entitySearchDirectionTranslations, PageComponent } from '@shared/public-api'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/public-api'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; +import { RelationsQuery } from '../rule-node-config.models'; + +@Component({ + selector: 'tb-relations-query-config-old', + templateUrl: './relations-query-config-old.component.html', + styleUrls: [], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RelationsQueryConfigOldComponent), + multi: true + } + ] +}) +export class RelationsQueryConfigOldComponent extends PageComponent implements ControlValueAccessor, OnInit { + + @Input() disabled: boolean; + + private requiredValue: boolean; + + get required(): boolean { + return this.requiredValue; + } + + @Input() + set required(value: boolean) { + this.requiredValue = coerceBooleanProperty(value); + } + + directionTypes = Object.keys(EntitySearchDirection); + directionTypeTranslations = entitySearchDirectionTranslations; + + relationsQueryFormGroup: FormGroup; + + private propagateChange = null; + + constructor(protected store: Store, + private fb: FormBuilder) { + super(store); + } + + ngOnInit(): void { + this.relationsQueryFormGroup = this.fb.group({ + fetchLastLevelOnly: [false, []], + direction: [null, [Validators.required]], + maxLevel: [null, []], + filters: [null] + }); + this.relationsQueryFormGroup.valueChanges.subscribe((query: RelationsQuery) => { + if (this.relationsQueryFormGroup.valid) { + this.propagateChange(query); + } else { + this.propagateChange(null); + } + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.relationsQueryFormGroup.disable({emitEvent: false}); + } else { + this.relationsQueryFormGroup.enable({emitEvent: false}); + } + } + + writeValue(query: RelationsQuery): void { + this.relationsQueryFormGroup.reset(query || {}, {emitEvent: false}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.html new file mode 100644 index 0000000000..748076957d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.html @@ -0,0 +1,61 @@ + +
    +
    tb.rulenode.relations-query
    +
    +
    + + relation.direction + + + {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix + + + + + tb.rulenode.max-relation-level + + + {{ 'tb.rulenode.max-relation-level-error' | translate }} + + + {{ 'tb.rulenode.max-relation-level-invalid' | translate }} + + +
    +
    + + {{ 'alias.last-level-relation' | translate }} + +
    +
    +
    +
    relation.relation-filters
    + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts new file mode 100644 index 0000000000..d17e6f891f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts @@ -0,0 +1,98 @@ +/// +/// 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, OnInit } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; +import { EntitySearchDirection, entitySearchDirectionTranslations, PageComponent } from '@shared/public-api'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/public-api'; +import { coerceBooleanProperty } from '@angular/cdk/coercion'; +import { RelationsQuery } from '../rule-node-config.models'; + +@Component({ + selector: 'tb-relations-query-config', + templateUrl: './relations-query-config.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => RelationsQueryConfigComponent), + multi: true + } + ] +}) +export class RelationsQueryConfigComponent extends PageComponent implements ControlValueAccessor, OnInit { + + @Input() disabled: boolean; + + private requiredValue: boolean; + + get required(): boolean { + return this.requiredValue; + } + + @Input() + set required(value: boolean) { + this.requiredValue = coerceBooleanProperty(value); + } + + directionTypes: Array = Object.values(EntitySearchDirection); + directionTypeTranslations = entitySearchDirectionTranslations; + + relationsQueryFormGroup: FormGroup; + + private propagateChange = null; + + constructor(protected store: Store, + private fb: FormBuilder) { + super(store); + } + + ngOnInit(): void { + this.relationsQueryFormGroup = this.fb.group({ + fetchLastLevelOnly: [false, []], + direction: [null, [Validators.required]], + maxLevel: [null, [Validators.min(1)]], + filters: [null] + }); + this.relationsQueryFormGroup.valueChanges.subscribe((query: RelationsQuery) => { + if (this.relationsQueryFormGroup.valid) { + this.propagateChange(query); + } else { + this.propagateChange(null); + } + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.relationsQueryFormGroup.disable({emitEvent: false}); + } else { + this.relationsQueryFormGroup.enable({emitEvent: false}); + } + } + + writeValue(query: RelationsQuery): void { + this.relationsQueryFormGroup.reset(query || {}, {emitEvent: false}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/rule-node-config-common.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/rule-node-config-common.module.ts new file mode 100644 index 0000000000..5b4a1e07fa --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/rule-node-config-common.module.ts @@ -0,0 +1,80 @@ +/// +/// 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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/public-api'; +import { HomeComponentsModule } from '@home/components/public-api'; +import { KvMapConfigComponent } from './kv-map-config.component'; +import { DeviceRelationsQueryConfigComponent } from './device-relations-query-config.component'; +import { RelationsQueryConfigComponent } from './relations-query-config.component'; +import { MessageTypesConfigComponent } from './message-types-config.component'; +import { CredentialsConfigComponent } from './credentials-config.component'; +import { ArgumentsMapConfigComponent } from './arguments-map-config.component'; +import { MathFunctionAutocompleteComponent } from './math-function-autocomplete.component'; +import { OutputMessageTypeAutocompleteComponent } from './output-message-type-autocomplete.component'; +import { KvMapConfigOldComponent } from './kv-map-config-old.component'; +import { MsgMetadataChipComponent } from './msg-metadata-chip.component'; +import { SvMapConfigComponent } from './sv-map-config.component'; +import { RelationsQueryConfigOldComponent } from './relations-query-config-old.component'; +import { SelectAttributesComponent } from './select-attributes.component'; +import { AlarmStatusSelectComponent } from './alarm-status-select.component'; +import { ExampleHintComponent } from './example-hint.component'; + +@NgModule({ + declarations: [ + KvMapConfigComponent, + DeviceRelationsQueryConfigComponent, + RelationsQueryConfigComponent, + MessageTypesConfigComponent, + CredentialsConfigComponent, + ArgumentsMapConfigComponent, + MathFunctionAutocompleteComponent, + OutputMessageTypeAutocompleteComponent, + KvMapConfigOldComponent, + MsgMetadataChipComponent, + SvMapConfigComponent, + RelationsQueryConfigOldComponent, + SelectAttributesComponent, + AlarmStatusSelectComponent, + ExampleHintComponent + ], + imports: [ + CommonModule, + SharedModule, + HomeComponentsModule + ], + exports: [ + KvMapConfigComponent, + DeviceRelationsQueryConfigComponent, + RelationsQueryConfigComponent, + MessageTypesConfigComponent, + CredentialsConfigComponent, + ArgumentsMapConfigComponent, + MathFunctionAutocompleteComponent, + OutputMessageTypeAutocompleteComponent, + KvMapConfigOldComponent, + MsgMetadataChipComponent, + SvMapConfigComponent, + RelationsQueryConfigOldComponent, + SelectAttributesComponent, + AlarmStatusSelectComponent, + ExampleHintComponent + ] +}) + +export class RuleNodeConfigCommonModule { +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html new file mode 100644 index 0000000000..ab7bea5409 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html @@ -0,0 +1,59 @@ + +
    + + + + + + + + + + + + + +
    + + {{ 'tb.rulenode.fetch-latest-telemetry-with-timestamp' | translate }} + +
    +
    + + + help + diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts new file mode 100644 index 0000000000..fbfbb63a14 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts @@ -0,0 +1,139 @@ +/// +/// 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, OnDestroy, OnInit } from '@angular/core'; +import { + ControlValueAccessor, + FormBuilder, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + ValidationErrors, + ValidatorFn, + Validators +} from '@angular/forms'; +import { takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; +import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; +import { TranslateService } from '@ngx-translate/core'; +import { isDefinedAndNotNull } from '@core/public-api'; + +@Component({ + selector: 'tb-select-attributes', + templateUrl: './select-attributes.component.html', + styleUrls: [], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SelectAttributesComponent), + multi: true + }, { + provide: NG_VALIDATORS, + useExisting: SelectAttributesComponent, + multi: true + }] +}) + +export class SelectAttributesComponent implements OnInit, ControlValueAccessor, OnDestroy { + + private propagateChange = (v: any) => { }; + private destroy$ = new Subject(); + + public attributeControlGroup: FormGroup; + public separatorKeysCodes = [ENTER, COMMA, SEMICOLON]; + public onTouched = () => {}; + + @Input() popupHelpLink: string; + + constructor(public translate: TranslateService, + private fb: FormBuilder) { + } + + ngOnInit(): void { + this.attributeControlGroup = this.fb.group({ + clientAttributeNames: [[], []], + sharedAttributeNames: [[], []], + serverAttributeNames: [[], []], + latestTsKeyNames: [[], []], + getLatestValueWithTs: [false, []] + }, { + validators: this.atLeastOne(Validators.required, ['clientAttributeNames', 'sharedAttributeNames', + 'serverAttributeNames', 'latestTsKeyNames']) + }); + + this.attributeControlGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + this.propagateChange(this.preparePropagateValue(value)); + }); + } + + private preparePropagateValue(propagateValue: {[key: string]: string[] | boolean | null}): {[key: string]: string[] | boolean } { + const formatValue = {}; + for (const key in propagateValue) { + if (key === 'getLatestValueWithTs') { + formatValue[key] = propagateValue[key]; + } else { + formatValue[key] = isDefinedAndNotNull(propagateValue[key]) ? propagateValue[key] : []; + } + }; + + return formatValue; + }; + + validate() { + if (this.attributeControlGroup.valid) { + return null; + } else { + return {atLeastOneRequired: true}; + } + } + + private atLeastOne(validator: ValidatorFn, controls: string[] = null) { + return (group: FormGroup): ValidationErrors | null => { + if (!controls) { + controls = Object.keys(group.controls); + } + const hasAtLeastOne = group?.controls && controls.some(k => !validator(group.controls[k])); + + return hasAtLeastOne ? null : {atLeastOne: true}; + }; + } + + writeValue(value): void { + this.attributeControlGroup.setValue(value, {emitEvent: false}); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + this.onTouched = fn; + } + + setDisabledState(isDisabled: boolean): void { + if (isDisabled) { + this.attributeControlGroup.disable({emitEvent: false}); + } else { + this.attributeControlGroup.enable({emitEvent: false}); + } + } + + ngOnDestroy(): void { + this.destroy$.next(null); + this.destroy$.complete(); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.html new file mode 100644 index 0000000000..6deeb54f67 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.html @@ -0,0 +1,70 @@ + +
    +
    +
    {{ labelText }}
    +
    + tb.rulenode.map-fields-required +
    +
    + {{ requiredText }} +
    +
    +
    +
    +
    +
    {{ selectText }}
    +
    {{ valText }}
    +
    +
    +
    +
    + + + + {{option.name}} + + + + + + +
    + +
    +
    +
    +
    +
    +
    + +
    + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.scss new file mode 100644 index 0000000000..132a1f882c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.scss @@ -0,0 +1,24 @@ +/** + * 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 { + .field-space { + flex: 1 1 50%; + } + + .actions-header { + width: 40px + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts new file mode 100644 index 0000000000..df9d3f0b3d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts @@ -0,0 +1,266 @@ +/// +/// 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, Injector, Input, OnDestroy, OnInit } from '@angular/core'; +import { + AbstractControl, + ControlValueAccessor, + FormArray, + FormBuilder, + FormControl, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + NgControl, + ValidationErrors, + Validator, + ValidatorFn, + Validators +} from '@angular/forms'; +import { coerceBoolean, PageComponent } from '@shared/public-api'; +import { Store } from '@ngrx/store'; +import { AppState, isDefinedAndNotNull, isEqual } from '@core/public-api'; +import { Subject, Subscription } from 'rxjs'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; +import { OriginatorFieldsMappingValues, SvMapOption } from '../rule-node-config.models'; + +@Component({ + selector: 'tb-sv-map-config', + templateUrl: './sv-map-config.component.html', + styleUrls: ['./sv-map-config.component.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => SvMapConfigComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => SvMapConfigComponent), + multi: true, + } + ] +}) +export class SvMapConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy { + + private destroy$ = new Subject(); + private sourceFieldSubcritption: Subscription[] = []; + private propagateChange = null; + + svListFormGroup: FormGroup; + ngControl: NgControl; + + @Input() selectOptions: SvMapOption[]; + + @Input() + @coerceBoolean() + disabled = false; + + @Input() labelText: string; + + @Input() requiredText: string; + + @Input() targetKeyPrefix: string; + + @Input() selectText: string; + + @Input() selectRequiredText: string; + + @Input() valText: string; + + @Input() valRequiredText: string; + + @Input() hintText: string; + + @Input() popupHelpLink: string; + + @Input() + @coerceBoolean() + required = false; + + constructor(protected store: Store, + public translate: TranslateService, + public injector: Injector, + private fb: FormBuilder) { + super(store); + } + + ngOnInit(): void { + this.ngControl = this.injector.get(NgControl); + if (this.ngControl != null) { + this.ngControl.valueAccessor = this; + } + + this.svListFormGroup = this.fb.group({ + keyVals: this.fb.array([]) + }, {validators: [this.propagateNestedErrors, this.oneMapRequiredValidator]}); + + this.svListFormGroup.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(() => { + this.updateModel(); + }); + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + + keyValsFormArray(): FormArray { + return this.svListFormGroup.get('keyVals') as FormArray; + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.svListFormGroup.disable({emitEvent: false}); + } else { + this.svListFormGroup.enable({emitEvent: false}); + } + } + + private oneMapRequiredValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => control.get('keyVals').value.length; + + private propagateNestedErrors: ValidatorFn = (controls: FormArray | FormGroup | AbstractControl): ValidationErrors | null => { + if (this.svListFormGroup && this.svListFormGroup.get('keyVals') && this.svListFormGroup.get('keyVals')?.status === 'VALID') { + return null; + } + const errors = {}; + if (this.svListFormGroup) {this.svListFormGroup.setErrors(null);} + if (controls instanceof FormArray || controls instanceof FormGroup) { + if (controls.errors) { + for (const errorKey of Object.keys(controls.errors)) { + errors[errorKey] = true; + } + } + for (const control of Object.keys(controls.controls)) { + const innerErrors = this.propagateNestedErrors(controls.controls[control]); + if (innerErrors && Object.keys(innerErrors).length) { + for (const errorKey of Object.keys(innerErrors)) { + errors[errorKey] = true; + } + } + } + return errors; + } else { + if (controls.errors) { + for (const errorKey of Object.keys(controls.errors)) { + errors[errorKey] = true; + } + } + } + return !isEqual(errors, {}) ? errors : null; + }; + + writeValue(keyValMap: { [key: string]: string }): void { + const keyValuesData = Object.keys(keyValMap).map(key => ({key, value: keyValMap[key]})); + if (this.keyValsFormArray().length === keyValuesData.length) { + this.keyValsFormArray().patchValue(keyValuesData, {emitEvent: false}) + } else { + const keyValsControls: Array = []; + keyValuesData.forEach(data => { + keyValsControls.push(this.fb.group({ + key: [data.key, [Validators.required, ]], + value: [data.value, [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]] + })); + }); + this.svListFormGroup.setControl('keyVals', this.fb.array(keyValsControls, this.propagateNestedErrors), {emitEvent: false}); + for (const formGroup of this.keyValsFormArray().controls) { + this.keyChangeSubscribe(formGroup as FormGroup); + } + } + } + + public filterSelectOptions(keyValControl?: AbstractControl) { + const deleteFieldsArray = []; + for (const fieldMap of this.svListFormGroup.get('keyVals').value) { + const findDeleteField = this.selectOptions.find((field) => field.value === fieldMap.key); + if (findDeleteField) { + deleteFieldsArray.push(findDeleteField); + } + } + + const filterSelectOptions = []; + for (const selectOption of this.selectOptions) { + if (!isDefinedAndNotNull(deleteFieldsArray.find((deleteField) => deleteField.value === selectOption.value)) || + selectOption.value === keyValControl?.get('key').value) { + filterSelectOptions.push(selectOption); + } + } + + return filterSelectOptions; + } + + public removeKeyVal(index: number) { + this.keyValsFormArray().removeAt(index); + this.sourceFieldSubcritption[index].unsubscribe(); + this.sourceFieldSubcritption.splice(index, 1); + } + + public addKeyVal() { + this.keyValsFormArray().push(this.fb.group({ + key: ['', [Validators.required]], + value: ['', [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]] + })); + this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length - 1) as FormGroup); + } + + private keyChangeSubscribe(formGroup: FormGroup) { + this.sourceFieldSubcritption.push(formGroup.get('key').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + const mappedValue = OriginatorFieldsMappingValues.get(value); + formGroup.get('value').patchValue(this.targetKeyPrefix + mappedValue[0].toUpperCase() + mappedValue.slice(1)); + })); + } + + public validate(c: FormControl) { + const svList: { key: string; value: string }[] = this.svListFormGroup.get('keyVals').value; + if (!svList.length && this.required) { + return { + svMapRequired: true + }; + } + if (!this.svListFormGroup.valid) { + return { + svFieldsRequired: true + }; + } + return null; + } + + private updateModel() { + const svList: { key: string; value: string }[] = this.svListFormGroup.get('keyVals').value; + if (this.required && !svList.length || !this.svListFormGroup.valid) { + this.propagateChange(null); + } else { + const keyValMap: { [key: string]: string } = {}; + svList.forEach((entry) => { + keyValMap[entry.key] = entry.value; + }); + this.propagateChange(keyValMap); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/empty-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/empty-config.component.ts new file mode 100644 index 0000000000..48f350157f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/empty-config.component.ts @@ -0,0 +1,42 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-node-empty-config', + template: '
    ', + styleUrls: [] +}) +export class EmptyConfigComponent extends RuleNodeConfigurationComponent { + + emptyConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.emptyConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.emptyConfigForm = this.fb.group({}); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.html new file mode 100644 index 0000000000..b727008bb3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.html @@ -0,0 +1,92 @@ + +
    +
    + + {{ 'tb.rulenode.input-value-key' | translate }} + + + {{ 'tb.rulenode.input-value-key-required' | translate }} + + + + {{ 'tb.rulenode.output-value-key' | translate }} + + + {{ 'tb.rulenode.output-value-key-required' | translate }} + + +
    + + {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }} + + + {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }} + + + {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }} + + +
    +
    + + {{ 'tb.rulenode.failure-if-delta-negative' | translate }} + +
    +
    + + {{ 'tb.rulenode.use-caching' | translate }} + +
    +
    +
    + + {{ 'tb.rulenode.add-time-difference-between-readings' | translate: + { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ? + calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }} + +
    + + {{ 'tb.rulenode.period-value-key' | translate }} + + + {{ 'tb.rulenode.period-value-key-required' | translate }} + + +
    +
    + + {{ 'tb.rulenode.exclude-zero-deltas' | translate }} + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.ts new file mode 100644 index 0000000000..1721b5dfb0 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-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 { Component } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { deepTrim, isDefinedAndNotNull } from '@app/core/utils'; + +@Component({ + selector: 'tb-enrichment-node-calculate-delta-config', + templateUrl: './calculate-delta-config.component.html' +}) +export class CalculateDeltaConfigComponent extends RuleNodeConfigurationComponent { + + calculateDeltaConfigForm: FormGroup; + + separatorKeysCodes = [ENTER, COMMA, SEMICOLON]; + + constructor(public translate: TranslateService, + private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.calculateDeltaConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.calculateDeltaConfigForm = this.fb.group({ + inputValueKey: [configuration.inputValueKey, [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]], + outputValueKey: [configuration.outputValueKey, [Validators.required, Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]], + useCache: [configuration.useCache, []], + addPeriodBetweenMsgs: [configuration.addPeriodBetweenMsgs, []], + periodValueKey: [configuration.periodValueKey, []], + round: [configuration.round, [Validators.min(0), Validators.max(15)]], + tellFailureIfDeltaIsNegative: [configuration.tellFailureIfDeltaIsNegative, []], + excludeZeroDeltas: [configuration.excludeZeroDeltas, []] + }); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + inputValueKey: isDefinedAndNotNull(configuration?.inputValueKey) ? configuration.inputValueKey : null, + outputValueKey: isDefinedAndNotNull(configuration?.outputValueKey) ? configuration.outputValueKey : null, + useCache: isDefinedAndNotNull(configuration?.useCache) ? configuration.useCache : true, + addPeriodBetweenMsgs: isDefinedAndNotNull(configuration?.addPeriodBetweenMsgs) ? configuration.addPeriodBetweenMsgs : false, + periodValueKey: isDefinedAndNotNull(configuration?.periodValueKey) ? configuration.periodValueKey : null, + round: isDefinedAndNotNull(configuration?.round) ? configuration.round : null, + tellFailureIfDeltaIsNegative: isDefinedAndNotNull(configuration?.tellFailureIfDeltaIsNegative) ? + configuration.tellFailureIfDeltaIsNegative : true, + excludeZeroDeltas: isDefinedAndNotNull(configuration?.excludeZeroDeltas) ? configuration.excludeZeroDeltas : false + }; + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return deepTrim(configuration); + } + + protected updateValidators(emitEvent: boolean) { + const addPeriodBetweenMsgs: boolean = this.calculateDeltaConfigForm.get('addPeriodBetweenMsgs').value; + if (addPeriodBetweenMsgs) { + this.calculateDeltaConfigForm.get('periodValueKey').setValidators([Validators.required]); + } else { + this.calculateDeltaConfigForm.get('periodValueKey').setValidators([]); + } + this.calculateDeltaConfigForm.get('periodValueKey').updateValueAndValidity({emitEvent}); + } + + protected validatorTriggers(): string[] { + return ['addPeriodBetweenMsgs']; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.html new file mode 100644 index 0000000000..182d580eec --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.html @@ -0,0 +1,46 @@ + +
    +
    tb.rulenode.mapping-of-customers
    +
    +
    + + + {{ data.name }} + + +
    +
    + + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.scss new file mode 100644 index 0000000000..aea1da60f3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.scss @@ -0,0 +1,23 @@ +/** + * 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 { + .fetch-to-data-toggle { + max-width: 420px; + width: 100%; + } +} + + diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.ts new file mode 100644 index 0000000000..3eabe0ab4f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.ts @@ -0,0 +1,100 @@ +/// +/// 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 { deepTrim, isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { DataToFetch, dataToFetchTranslations, FetchTo } from '@home/components/rule-node/rule-node-config.models'; + +@Component({ + selector: 'tb-enrichment-node-customer-attributes-config', + templateUrl: './customer-attributes-config.component.html', + styleUrls: ['./customer-attributes-config.component.scss'] +}) +export class CustomerAttributesConfigComponent extends RuleNodeConfigurationComponent { + + customerAttributesConfigForm: FormGroup; + + public fetchToData = []; + + constructor(private fb: FormBuilder, + private translate: TranslateService) { + super(); + for (const key of dataToFetchTranslations.keys()) { + if (key !== DataToFetch.FIELDS) { + this.fetchToData.push({ + value: key, + name: this.translate.instant(dataToFetchTranslations.get(key as DataToFetch)) + }); + } + } + } + + protected configForm(): FormGroup { + return this.customerAttributesConfigForm; + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + const filteDataMapping = {}; + for (const key of Object.keys(configuration.dataMapping)) { + filteDataMapping[key.trim()] = configuration.dataMapping[key]; + } + configuration.dataMapping = filteDataMapping; + return deepTrim(configuration); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + let dataToFetch: DataToFetch; + if (isDefinedAndNotNull(configuration?.telemetry)) { + dataToFetch = configuration.telemetry ? DataToFetch.LATEST_TELEMETRY : DataToFetch.ATTRIBUTES; + } else { + dataToFetch = isDefinedAndNotNull(configuration?.dataToFetch) ? configuration.dataToFetch : DataToFetch.ATTRIBUTES; + } + + let dataMapping; + if (isDefinedAndNotNull(configuration?.attrMapping)) { + dataMapping = configuration.attrMapping; + } else { + dataMapping = isDefinedAndNotNull(configuration?.dataMapping) ? configuration.dataMapping : null; + } + + return { + dataToFetch, + dataMapping, + fetchTo: isDefinedAndNotNull(configuration?.fetchTo) ? configuration.fetchTo : FetchTo.METADATA + }; + } + + public selectTranslation(latestTelemetryTranslation: string, attributesTranslation: string) { + if (this.customerAttributesConfigForm.get('dataToFetch').value === DataToFetch.LATEST_TELEMETRY) { + return latestTelemetryTranslation; + } else { + return attributesTranslation; + } + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.customerAttributesConfigForm = this.fb.group({ + dataToFetch: [configuration.dataToFetch, []], + dataMapping: [configuration.dataMapping, [Validators.required]], + fetchTo: [configuration.fetchTo] + }); + } + + protected readonly DataToFetch = DataToFetch; +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.html new file mode 100644 index 0000000000..c17edb1e92 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.html @@ -0,0 +1,46 @@ + +
    +
    +
    tb.rulenode.device-relations-query
    + + +
    +
    +
    +
    tb.rulenode.related-device-attributes
    +
    + tb.rulenode.at-least-one-field-required +
    +
    + + +
    +
    + + {{ 'tb.rulenode.tell-failure' | translate }} + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.ts new file mode 100644 index 0000000000..876e672b13 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.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 { Component } from '@angular/core'; +import { isDefinedAndNotNull, isObject } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { FetchTo } from '@home/components/rule-node/rule-node-config.models'; + +@Component({ + selector: 'tb-enrichment-node-device-attributes-config', + templateUrl: './device-attributes-config.component.html', + styleUrls: [] +}) +export class DeviceAttributesConfigComponent extends RuleNodeConfigurationComponent { + + deviceAttributesConfigForm: FormGroup; + + constructor(public translate: TranslateService, + private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.deviceAttributesConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.deviceAttributesConfigForm = this.fb.group({ + deviceRelationsQuery: [configuration.deviceRelationsQuery, [Validators.required]], + tellFailureIfAbsent: [configuration.tellFailureIfAbsent, []], + fetchTo: [configuration.fetchTo, []], + attributesControl: [configuration.attributesControl, []] + }); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (isObject(configuration)) { + configuration.attributesControl = { + clientAttributeNames: isDefinedAndNotNull(configuration?.clientAttributeNames) ? configuration.clientAttributeNames : [], + latestTsKeyNames: isDefinedAndNotNull(configuration?.latestTsKeyNames) ? configuration.latestTsKeyNames : [], + serverAttributeNames: isDefinedAndNotNull(configuration?.serverAttributeNames) ? configuration.serverAttributeNames : [], + sharedAttributeNames: isDefinedAndNotNull(configuration?.sharedAttributeNames) ? configuration.sharedAttributeNames : [], + getLatestValueWithTs: isDefinedAndNotNull(configuration?.getLatestValueWithTs) ? configuration.getLatestValueWithTs : false, + }; + } + + return { + deviceRelationsQuery: isDefinedAndNotNull(configuration?.deviceRelationsQuery) ? configuration.deviceRelationsQuery : null, + tellFailureIfAbsent: isDefinedAndNotNull(configuration?.tellFailureIfAbsent) ? configuration.tellFailureIfAbsent : true, + fetchTo: isDefinedAndNotNull(configuration?.fetchTo) ? configuration.fetchTo : FetchTo.METADATA, + attributesControl: configuration ? configuration.attributesControl : null + }; + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + for (const key of Object.keys(configuration.attributesControl)) { + configuration[key] = configuration.attributesControl[key]; + } + delete configuration.attributesControl; + return configuration; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.html new file mode 100644 index 0000000000..1065aa6a09 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.html @@ -0,0 +1,35 @@ + +
    + + + help + + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.ts new file mode 100644 index 0000000000..808eaf35b2 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-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 { Component, OnInit } from '@angular/core'; +import { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { + EntityDetailsField, + entityDetailsTranslations, + FetchTo +} from '@home/components/rule-node/rule-node-config.models'; + +@Component({ + selector: 'tb-enrichment-node-entity-details-config', + templateUrl: './entity-details-config.component.html', + styleUrls: [] +}) + +export class EntityDetailsConfigComponent extends RuleNodeConfigurationComponent implements OnInit { + + entityDetailsConfigForm: FormGroup; + + public predefinedValues = []; + + constructor(public translate: TranslateService, + private fb: FormBuilder) { + super(); + for (const field of Object.keys(EntityDetailsField)) { + this.predefinedValues.push({ + value: EntityDetailsField[field], + name: this.translate.instant(entityDetailsTranslations.get(EntityDetailsField[field])) + }); + } + } + + ngOnInit() { + super.ngOnInit(); + } + + protected configForm(): FormGroup { + return this.entityDetailsConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + let fetchTo: FetchTo; + if (isDefinedAndNotNull(configuration?.addToMetadata)) { + if (configuration.addToMetadata) { + fetchTo = FetchTo.METADATA; + } else { + fetchTo = FetchTo.DATA; + } + } else { + if (configuration?.fetchTo) { + fetchTo = configuration.fetchTo; + } else { + fetchTo = FetchTo.DATA; + } + } + + return { + detailsList: isDefinedAndNotNull(configuration?.detailsList) ? configuration.detailsList : null, + fetchTo + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.entityDetailsConfigForm = this.fb.group({ + detailsList: [configuration.detailsList, [Validators.required]], + fetchTo: [configuration.fetchTo, []] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.html new file mode 100644 index 0000000000..a76d3341d7 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.html @@ -0,0 +1,23 @@ + +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.ts new file mode 100644 index 0000000000..1b16674566 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.ts @@ -0,0 +1,51 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { FetchTo } from '@home/components/rule-node/rule-node-config.models'; + +@Component({ + selector: 'tb-enrichment-node-fetch-device-credentials-config', + templateUrl: './fetch-device-credentials-config.component.html' +}) + +export class FetchDeviceCredentialsConfigComponent extends RuleNodeConfigurationComponent { + + fetchDeviceCredentialsConfigForm: FormGroup; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.fetchDeviceCredentialsConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + fetchTo: isDefinedAndNotNull(configuration?.fetchTo) ? configuration.fetchTo : FetchTo.METADATA + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.fetchDeviceCredentialsConfigForm = this.fb.group({ + fetchTo: [configuration.fetchTo, []] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.html new file mode 100644 index 0000000000..450ba10d95 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.html @@ -0,0 +1,182 @@ + +
    + +
    + help + +
    +
    +
    tb.rulenode.fetch-interval
    +
    + + {{ 'tb.rulenode.use-metadata-dynamic-interval' | translate }} + +
    +
    +
    + + {{ 'tb.rulenode.interval-start' | translate }} + + + {{ 'tb.rulenode.start-interval-value-required' | translate }} + + + {{ 'tb.rulenode.time-value-range' | translate }} + + + {{ 'tb.rulenode.time-value-range' | translate }} + + + + {{ 'tb.rulenode.time-unit' | translate }} + + + {{ timeUnitsTranslationMap.get(timeUnit) | translate }} + + + +
    +
    + + {{ 'tb.rulenode.interval-end' | translate }} + + + {{ 'tb.rulenode.end-interval-value-required' | translate }} + + + {{ 'tb.rulenode.time-value-range' | translate }} + + + {{ 'tb.rulenode.time-value-range' | translate }} + + + + {{ 'tb.rulenode.time-unit' | translate }} + + + {{ timeUnitsTranslationMap.get(timeUnit) | translate }} + + + +
    +
    + error_outline +
    + + {{ 'tb.rulenode.fetch-timeseries-from-to' | translate: + { + startInterval: getTelemetryFromDatabaseConfigForm.get('interval.startInterval').value, + endInterval: getTelemetryFromDatabaseConfigForm.get('interval.endInterval').value, + startIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get('interval.startIntervalTimeUnit').value.toLowerCase(), + endIntervalTimeUnit: getTelemetryFromDatabaseConfigForm.get('interval.endIntervalTimeUnit').value.toLowerCase() + } }} + + + {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }} + +
    +
    +
    + +
    + + {{ 'tb.rulenode.start-interval' | translate }} + + + {{ 'tb.rulenode.start-interval-required' | translate }} + + + + {{ 'tb.rulenode.end-interval' | translate }} + + + {{ 'tb.rulenode.end-interval-required' | translate }} + + + + +
    +
    +
    +
    +
    tb.rulenode.fetch-strategy
    +
    +
    + + + {{ data.name }} + + +
    +
    + {{ deduplicationStrategiesHintTranslations.get(getTelemetryFromDatabaseConfigForm.get('fetchMode').value) | translate }} +
    +
    +
    + + {{ 'aggregation.function' | translate }} + + + {{ aggregationTypesTranslations.get(aggregationTypes[aggregation]) | translate }} + + + +
    + + {{ "tb.rulenode.order-by-timestamp" | translate }} + + + {{ samplingOrdersTranslate.get(order) | translate }} + + + + + {{ "tb.rulenode.limit" | translate }} + + {{ "tb.rulenode.limit-hint" | translate }} + + {{ 'tb.rulenode.limit-required' | translate }} + + + {{ 'tb.rulenode.limit-range' | translate }} + + + {{ 'tb.rulenode.limit-range' | translate }} + + +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.scss new file mode 100644 index 0000000000..f1fe8725e3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.scss @@ -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. + */ +:host { + + .see-example { + display: inline-block; + } + + .description-block { + display: flex; + align-items: center; + border-radius: 6px; + border: 1px solid #EAEAEA; + + .description-icon { + font-size: 24px; + height: 24px; + min-height: 24px; + width: 24px; + min-width: 24px; + line-height: 24px; + color: #D9D9D9; + margin: 4px; + } + + .description-text { + font-size: 12px; + line-height: 16px; + letter-spacing: 0.25px; + margin: 6px; + } + + &.error { + color: var(--mdc-theme-error, #f44336); + + .description-icon { + color: var(--mdc-theme-error, #f44336); + } + } + } + .item-center { + align-items: center; + + .fetch-mod-toggle { + width: 100%; + } + } + + .hint-container { + width: 100%; + } +} + diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.ts new file mode 100644 index 0000000000..13aeae87ed --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.ts @@ -0,0 +1,205 @@ +/// +/// 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 { deepTrim, isDefinedAndNotNull, isObject } from '@core/public-api'; +import { AbstractControl, FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { aggregationTranslations, AggregationType } from '@app/shared/models/time/time.models'; +import { + deduplicationStrategiesHintTranslations, + deduplicationStrategiesTranslations, + FetchMode, + SamplingOrder, + samplingOrderTranslations, + TimeUnit, + timeUnitTranslations +} from '../rule-node-config.models'; + +@Component({ + selector: 'tb-enrichment-node-get-telemetry-from-database', + templateUrl: './get-telemetry-from-database-config.component.html', + styleUrls: ['./get-telemetry-from-database-config.component.scss'] +}) +export class GetTelemetryFromDatabaseConfigComponent extends RuleNodeConfigurationComponent { + + getTelemetryFromDatabaseConfigForm: FormGroup; + + aggregationTypes = AggregationType; + aggregations: Array = Object.values(AggregationType); + aggregationTypesTranslations = aggregationTranslations; + + fetchMode = FetchMode; + + samplingOrders: Array = Object.values(SamplingOrder); + samplingOrdersTranslate = samplingOrderTranslations; + + timeUnits: Array = Object.values(TimeUnit); + timeUnitsTranslationMap = timeUnitTranslations; + + public deduplicationStrategiesHintTranslations = deduplicationStrategiesHintTranslations; + + headerOptions = []; + + + timeUnitMap = { + [TimeUnit.MILLISECONDS]: 1, + [TimeUnit.SECONDS]: 1000, + [TimeUnit.MINUTES]: 60000, + [TimeUnit.HOURS]: 3600000, + [TimeUnit.DAYS]: 86400000, + }; + + constructor(public translate: TranslateService, + private fb: FormBuilder) { + super(); + for (const key of deduplicationStrategiesTranslations.keys()) { + this.headerOptions.push({ + value: key, + name: this.translate.instant(deduplicationStrategiesTranslations.get(key)) + }); + } + } + + protected configForm(): FormGroup { + return this.getTelemetryFromDatabaseConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.getTelemetryFromDatabaseConfigForm = this.fb.group({ + latestTsKeyNames: [configuration.latestTsKeyNames, [Validators.required]], + aggregation: [configuration.aggregation, [Validators.required]], + fetchMode: [configuration.fetchMode, [Validators.required]], + orderBy: [configuration.orderBy, []], + limit: [configuration.limit, []], + useMetadataIntervalPatterns: [configuration.useMetadataIntervalPatterns, []], + interval: this.fb.group({ + startInterval: [configuration.interval.startInterval, []], + startIntervalTimeUnit: [configuration.interval.startIntervalTimeUnit, []], + endInterval: [configuration.interval.endInterval, []], + endIntervalTimeUnit: [configuration.interval.endIntervalTimeUnit, []], + }), + startIntervalPattern: [configuration.startIntervalPattern, []], + endIntervalPattern: [configuration.endIntervalPattern, []], + }); + } + + + private intervalValidator = () => (control: AbstractControl): ValidationErrors | null => { + if (control.get('startInterval').value * this.timeUnitMap[control.get('startIntervalTimeUnit').value] <= + control.get('endInterval').value * this.timeUnitMap[control.get('endIntervalTimeUnit').value]) { + return {intervalError: true}; + } else { + return null; + } + }; + + + protected validatorTriggers(): string[] { + return ['fetchMode', 'useMetadataIntervalPatterns']; + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + configuration.startInterval = configuration.interval.startInterval; + configuration.startIntervalTimeUnit = configuration.interval.startIntervalTimeUnit; + configuration.endInterval = configuration.interval.endInterval; + configuration.endIntervalTimeUnit = configuration.interval.endIntervalTimeUnit; + delete configuration.interval; + return deepTrim(configuration); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (isObject(configuration)) { + configuration.interval = { + startInterval: configuration.startInterval, + startIntervalTimeUnit: configuration.startIntervalTimeUnit, + endInterval: configuration.endInterval, + endIntervalTimeUnit: configuration.endIntervalTimeUnit + }; + } + + return { + latestTsKeyNames: isDefinedAndNotNull(configuration?.latestTsKeyNames) ? configuration.latestTsKeyNames : null, + aggregation: isDefinedAndNotNull(configuration?.aggregation) ? configuration.aggregation : AggregationType.NONE, + fetchMode: isDefinedAndNotNull(configuration?.fetchMode) ? configuration.fetchMode : FetchMode.FIRST, + orderBy: isDefinedAndNotNull(configuration?.orderBy) ? configuration.orderBy : SamplingOrder.ASC, + limit: isDefinedAndNotNull(configuration?.limit) ? configuration.limit : 1000, + useMetadataIntervalPatterns: isDefinedAndNotNull(configuration?.useMetadataIntervalPatterns) ? + configuration.useMetadataIntervalPatterns : false, + interval: { + startInterval: isDefinedAndNotNull(configuration?.interval?.startInterval) ? configuration.interval.startInterval : 2, + startIntervalTimeUnit: isDefinedAndNotNull(configuration?.interval?.startIntervalTimeUnit) ? + configuration.interval.startIntervalTimeUnit : TimeUnit.MINUTES, + endInterval: isDefinedAndNotNull(configuration?.interval?.endInterval) ? configuration.interval.endInterval : 1, + endIntervalTimeUnit: isDefinedAndNotNull(configuration?.interval?.endIntervalTimeUnit) ? + configuration.interval.endIntervalTimeUnit : TimeUnit.MINUTES, + }, + startIntervalPattern: isDefinedAndNotNull(configuration?.startIntervalPattern) ? configuration.startIntervalPattern : null, + endIntervalPattern: isDefinedAndNotNull(configuration?.endIntervalPattern) ? configuration.endIntervalPattern : null + }; + } + + protected updateValidators(emitEvent: boolean) { + const fetchMode: FetchMode = this.getTelemetryFromDatabaseConfigForm.get('fetchMode').value; + const useMetadataIntervalPatterns: boolean = this.getTelemetryFromDatabaseConfigForm.get('useMetadataIntervalPatterns').value; + if (fetchMode && fetchMode === FetchMode.ALL) { + this.getTelemetryFromDatabaseConfigForm.get('aggregation').setValidators([Validators.required]); + this.getTelemetryFromDatabaseConfigForm.get('orderBy').setValidators([Validators.required]); + this.getTelemetryFromDatabaseConfigForm.get('limit').setValidators([Validators.required, Validators.min(2), Validators.max(1000)]); + } else { + this.getTelemetryFromDatabaseConfigForm.get('aggregation').setValidators([]); + this.getTelemetryFromDatabaseConfigForm.get('orderBy').setValidators([]); + this.getTelemetryFromDatabaseConfigForm.get('limit').setValidators([]); + } + if (useMetadataIntervalPatterns) { + 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([Validators.required, + Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]); + this.getTelemetryFromDatabaseConfigForm.get('endIntervalPattern').setValidators([Validators.required, + Validators.pattern(/(?:.|\s)*\S(&:.|\s)*/)]); + } else { + this.getTelemetryFromDatabaseConfigForm.get('interval.startInterval').setValidators([Validators.required, + Validators.min(1), Validators.max(2147483647)]); + this.getTelemetryFromDatabaseConfigForm.get('interval.startIntervalTimeUnit').setValidators([Validators.required]); + this.getTelemetryFromDatabaseConfigForm.get('interval.endInterval').setValidators([Validators.required, + Validators.min(1), Validators.max(2147483647)]); + this.getTelemetryFromDatabaseConfigForm.get('interval.endIntervalTimeUnit').setValidators([Validators.required]); + this.getTelemetryFromDatabaseConfigForm.get('interval').setValidators([this.intervalValidator()]); + this.getTelemetryFromDatabaseConfigForm.get('startIntervalPattern').setValidators([]); + this.getTelemetryFromDatabaseConfigForm.get('endIntervalPattern').setValidators([]); + } + this.getTelemetryFromDatabaseConfigForm.get('aggregation').updateValueAndValidity({emitEvent}); + this.getTelemetryFromDatabaseConfigForm.get('orderBy').updateValueAndValidity({emitEvent}); + this.getTelemetryFromDatabaseConfigForm.get('limit').updateValueAndValidity({emitEvent}); + this.getTelemetryFromDatabaseConfigForm.get('interval.startInterval').updateValueAndValidity({emitEvent}); + this.getTelemetryFromDatabaseConfigForm.get('interval.startIntervalTimeUnit').updateValueAndValidity({emitEvent}); + this.getTelemetryFromDatabaseConfigForm.get('interval.endInterval').updateValueAndValidity({emitEvent}); + this.getTelemetryFromDatabaseConfigForm.get('interval.endIntervalTimeUnit').updateValueAndValidity({emitEvent}); + this.getTelemetryFromDatabaseConfigForm.get('interval').updateValueAndValidity({emitEvent}); + this.getTelemetryFromDatabaseConfigForm.get('startIntervalPattern').updateValueAndValidity({emitEvent}); + this.getTelemetryFromDatabaseConfigForm.get('endIntervalPattern').updateValueAndValidity({emitEvent}); + } + + public defaultPaddingEnable() { + return this.getTelemetryFromDatabaseConfigForm.get('fetchMode').value === FetchMode.ALL && + this.getTelemetryFromDatabaseConfigForm.get('aggregation').value === AggregationType.NONE; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.html new file mode 100644 index 0000000000..caf7c63d11 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.html @@ -0,0 +1,40 @@ + +
    +
    +
    +
    tb.rulenode.originator-attributes
    +
    + tb.rulenode.at-least-one-field-required +
    +
    + + + + +
    +
    + + {{ 'tb.rulenode.tell-failure' | translate }} + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.ts new file mode 100644 index 0000000000..b0ff9e0098 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.ts @@ -0,0 +1,75 @@ +/// +/// 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 { isDefinedAndNotNull, isObject, } from '@core/public-api'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { FetchTo } from '@home/components/rule-node/rule-node-config.models'; + +@Component({ + selector: 'tb-enrichment-node-originator-attributes-config', + templateUrl: './originator-attributes-config.component.html', + styleUrls: [] +}) +export class OriginatorAttributesConfigComponent extends RuleNodeConfigurationComponent { + + originatorAttributesConfigForm: FormGroup; + + constructor(public translate: TranslateService, + private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.originatorAttributesConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.originatorAttributesConfigForm = this.fb.group({ + tellFailureIfAbsent: [configuration.tellFailureIfAbsent, []], + fetchTo: [configuration.fetchTo, []], + attributesControl: [configuration.attributesControl, []] + }); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (isObject(configuration)) { + configuration.attributesControl = { + clientAttributeNames: isDefinedAndNotNull(configuration?.clientAttributeNames) ? configuration.clientAttributeNames : [], + latestTsKeyNames: isDefinedAndNotNull(configuration?.latestTsKeyNames) ? configuration.latestTsKeyNames : [], + serverAttributeNames: isDefinedAndNotNull(configuration?.serverAttributeNames) ? configuration.serverAttributeNames : [], + sharedAttributeNames: isDefinedAndNotNull(configuration?.sharedAttributeNames) ? configuration.sharedAttributeNames : [], + getLatestValueWithTs: isDefinedAndNotNull(configuration?.getLatestValueWithTs) ? configuration.getLatestValueWithTs : false + }; + } + + return { + fetchTo: isDefinedAndNotNull(configuration?.fetchTo) ? configuration.fetchTo : FetchTo.METADATA, + tellFailureIfAbsent: isDefinedAndNotNull(configuration?.tellFailureIfAbsent) ? configuration.tellFailureIfAbsent : false, + attributesControl: isDefinedAndNotNull(configuration?.attributesControl) ? configuration.attributesControl : null + }; + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + for (const key of Object.keys(configuration.attributesControl)) { + configuration[key] = configuration.attributesControl[key]; + } + delete configuration.attributesControl; + return configuration; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.html new file mode 100644 index 0000000000..6ec066f230 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.html @@ -0,0 +1,41 @@ + +
    + + + + +
    + + {{ 'tb.rulenode.skip-empty-fields' | translate }} + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.ts new file mode 100644 index 0000000000..d291bb56d3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.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 { Component } from '@angular/core'; +import { deepTrim, isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { allowedOriginatorFields, FetchTo, SvMapOption } from '@home/components/rule-node/rule-node-config.models'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; + +@Component({ + selector: 'tb-enrichment-node-originator-fields-config', + templateUrl: './originator-fields-config.component.html' +}) +export class OriginatorFieldsConfigComponent extends RuleNodeConfigurationComponent { + + originatorFieldsConfigForm: FormGroup; + public originatorFields: SvMapOption[] = []; + + constructor(private fb: FormBuilder, + private translate: TranslateService) { + super(); + for (const field of allowedOriginatorFields) { + this.originatorFields.push({ + value: field.value, + name: this.translate.instant(field.name) + }); + } + } + + protected configForm(): FormGroup { + return this.originatorFieldsConfigForm; + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return deepTrim(configuration); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + dataMapping: isDefinedAndNotNull(configuration?.dataMapping) ? configuration.dataMapping : null, + ignoreNullStrings: isDefinedAndNotNull(configuration?.ignoreNullStrings) ? configuration.ignoreNullStrings : null, + fetchTo: isDefinedAndNotNull(configuration?.fetchTo) ? configuration.fetchTo : FetchTo.METADATA + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.originatorFieldsConfigForm = this.fb.group({ + dataMapping: [configuration.dataMapping, [Validators.required]], + ignoreNullStrings: [configuration.ignoreNullStrings, []], + fetchTo: [configuration.fetchTo, []] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.html new file mode 100644 index 0000000000..a7d9f74e1d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.html @@ -0,0 +1,62 @@ + +
    + + +
    +
    tb.rulenode.data-to-fetch
    + + + {{ data.name }} + + + + + + + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.ts new file mode 100644 index 0000000000..8446479cf4 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.ts @@ -0,0 +1,160 @@ +/// +/// 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 { deepTrim, isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { + allowedOriginatorFields, + DataToFetch, + dataToFetchTranslations, + FetchTo, + msgMetadataLabelTranslations, + SvMapOption +} from '../rule-node-config.models'; +import { entityFields } from '@shared/models/entity.models'; + +@Component({ + selector: 'tb-enrichment-node-related-attributes-config', + templateUrl: './related-attributes-config.component.html', + styleUrls: [] +}) +export class RelatedAttributesConfigComponent extends RuleNodeConfigurationComponent { + + relatedAttributesConfigForm: FormGroup; + + protected readonly DataToFetch = DataToFetch; + + public msgMetadataLabelTranslations = msgMetadataLabelTranslations; + public originatorFields: SvMapOption[] = []; + public fetchToData = []; + + constructor(private fb: FormBuilder, + private translate: TranslateService) { + super(); + for (const field of Object.keys(allowedOriginatorFields)) { + this.originatorFields.push({ + value: allowedOriginatorFields[field].value, + name: this.translate.instant(allowedOriginatorFields[field].name) + }); + } + for (const key of dataToFetchTranslations.keys()) { + this.fetchToData.push({ + value: key, + name: this.translate.instant(dataToFetchTranslations.get(key as DataToFetch)) + }); + } + } + + protected configForm(): FormGroup { + return this.relatedAttributesConfigForm; + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (configuration.dataToFetch === DataToFetch.FIELDS) { + configuration.dataMapping = configuration.svMap; + delete configuration.svMap; + } else { + configuration.dataMapping = configuration.kvMap; + delete configuration.kvMap; + } + + const filteDataMapping = {}; + if (configuration && configuration.dataMapping) { + for (const key of Object.keys(configuration.dataMapping)) { + filteDataMapping[key.trim()] = configuration.dataMapping[key]; + } + } + configuration.dataMapping = filteDataMapping; + delete configuration.svMap; + delete configuration.kvMap; + + return deepTrim(configuration); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + let svMap = { + [entityFields.name.value]: `relatedEntity${this.translate.instant(entityFields.name.name)}` + }; + let kvMap = { + serialNumber: 'sn' + }; + + let dataToFetch: DataToFetch; + if (isDefinedAndNotNull(configuration?.telemetry)) { + dataToFetch = configuration.telemetry ? DataToFetch.LATEST_TELEMETRY : DataToFetch.ATTRIBUTES; + } else { + dataToFetch = isDefinedAndNotNull(configuration?.dataToFetch) ? configuration.dataToFetch : DataToFetch.ATTRIBUTES; + } + + let dataMapping; + if (isDefinedAndNotNull(configuration?.attrMapping)) { + dataMapping = configuration.attrMapping; + } else { + dataMapping = isDefinedAndNotNull(configuration?.dataMapping) ? configuration.dataMapping : null; + } + + if (dataToFetch === DataToFetch.FIELDS) { + svMap = dataMapping; + } else { + kvMap = dataMapping; + } + + return { + relationsQuery: isDefinedAndNotNull(configuration?.relationsQuery) ? configuration.relationsQuery : null, + dataToFetch, + svMap, + kvMap, + fetchTo: isDefinedAndNotNull(configuration?.fetchTo) ? configuration.fetchTo : FetchTo.METADATA + }; + } + + public selectTranslation(latestTelemetryTranslation: string, attributesTranslation: string) { + if (this.relatedAttributesConfigForm.get('dataToFetch').value === DataToFetch.LATEST_TELEMETRY) { + return latestTelemetryTranslation; + } else { + return attributesTranslation; + } + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.relatedAttributesConfigForm = this.fb.group({ + relationsQuery: [configuration.relationsQuery, [Validators.required]], + dataToFetch: [configuration.dataToFetch, []], + kvMap: [configuration.kvMap, [Validators.required]], + svMap: [configuration.svMap, [Validators.required]], + fetchTo: [configuration.fetchTo, []] + }); + } + + protected validatorTriggers(): string[] { + return ['dataToFetch']; + } + + protected updateValidators(emitEvent: boolean) { + if (this.relatedAttributesConfigForm.get('dataToFetch').value === DataToFetch.FIELDS) { + this.relatedAttributesConfigForm.get('svMap').enable({emitEvent: false}); + this.relatedAttributesConfigForm.get('kvMap').disable({emitEvent: false}); + this.relatedAttributesConfigForm.get('svMap').updateValueAndValidity(); + } else { + this.relatedAttributesConfigForm.get('svMap').disable({emitEvent: false}); + this.relatedAttributesConfigForm.get('kvMap').enable({emitEvent: false}); + this.relatedAttributesConfigForm.get('kvMap').updateValueAndValidity(); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/rule-node-core-enrichment.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/rule-node-core-enrichment.module.ts new file mode 100644 index 0000000000..2855344801 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/rule-node-core-enrichment.module.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 { NgModule, Type } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { CustomerAttributesConfigComponent } from './customer-attributes-config.component'; +import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.module'; +import { EntityDetailsConfigComponent } from './entity-details-config.component'; +import { DeviceAttributesConfigComponent } from './device-attributes-config.component'; +import { OriginatorAttributesConfigComponent } from './originator-attributes-config.component'; +import { OriginatorFieldsConfigComponent } from './originator-fields-config.component'; +import { GetTelemetryFromDatabaseConfigComponent } from './get-telemetry-from-database-config.component'; +import { RelatedAttributesConfigComponent } from './related-attributes-config.component'; +import { TenantAttributesConfigComponent } from './tenant-attributes-config.component'; +import { CalculateDeltaConfigComponent } from './calculate-delta-config.component'; +import { FetchDeviceCredentialsConfigComponent } from './fetch-device-credentials-config.component'; + +@NgModule({ + declarations: [ + CustomerAttributesConfigComponent, + EntityDetailsConfigComponent, + DeviceAttributesConfigComponent, + OriginatorAttributesConfigComponent, + OriginatorFieldsConfigComponent, + GetTelemetryFromDatabaseConfigComponent, + RelatedAttributesConfigComponent, + TenantAttributesConfigComponent, + CalculateDeltaConfigComponent, + FetchDeviceCredentialsConfigComponent + ], + imports: [ + CommonModule, + SharedModule, + RuleNodeConfigCommonModule + ], + exports: [ + CustomerAttributesConfigComponent, + EntityDetailsConfigComponent, + DeviceAttributesConfigComponent, + OriginatorAttributesConfigComponent, + OriginatorFieldsConfigComponent, + GetTelemetryFromDatabaseConfigComponent, + RelatedAttributesConfigComponent, + TenantAttributesConfigComponent, + CalculateDeltaConfigComponent, + FetchDeviceCredentialsConfigComponent + ] +}) +export class RuleNodeCoreEnrichmentModule { +} + +export const ruleNodeEnrichmentConfigComponentsMap: Record> = { + 'tbEnrichmentNodeCalculateDeltaConfig': CalculateDeltaConfigComponent, + 'tbEnrichmentNodeCustomerAttributesConfig': CustomerAttributesConfigComponent, + 'tbEnrichmentNodeDeviceAttributesConfig': DeviceAttributesConfigComponent, + 'tbEnrichmentNodeEntityDetailsConfig': EntityDetailsConfigComponent, + 'tbEnrichmentNodeFetchDeviceCredentialsConfig': FetchDeviceCredentialsConfigComponent, + 'tbEnrichmentNodeGetTelemetryFromDatabase': GetTelemetryFromDatabaseConfigComponent, + 'tbEnrichmentNodeOriginatorAttributesConfig': OriginatorAttributesConfigComponent, + 'tbEnrichmentNodeOriginatorFieldsConfig': OriginatorFieldsConfigComponent, + 'tbEnrichmentNodeRelatedAttributesConfig': RelatedAttributesConfigComponent, + 'tbEnrichmentNodeTenantAttributesConfig': TenantAttributesConfigComponent +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.html new file mode 100644 index 0000000000..abdc84ed63 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.html @@ -0,0 +1,45 @@ + +
    +
    tb.rulenode.mapping-of-tenant
    +
    +
    + + + {{ data.name }} + + +
    +
    + + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.scss new file mode 100644 index 0000000000..4943a8fa07 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.scss @@ -0,0 +1,21 @@ +/** + * 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 { + .fetch-to-data-toggle { + max-width: 420px; + width: 100%; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.ts new file mode 100644 index 0000000000..2c05d3369f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/tenant-attributes-config.component.ts @@ -0,0 +1,91 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { DataToFetch, dataToFetchTranslations, FetchTo } from '../rule-node-config.models'; + +@Component({ + selector: 'tb-enrichment-node-tenant-attributes-config', + templateUrl: './tenant-attributes-config.component.html', + styleUrls: ['./tenant-attributes-config.component.scss'] +}) +export class TenantAttributesConfigComponent extends RuleNodeConfigurationComponent { + + tenantAttributesConfigForm: FormGroup; + public fetchToData = []; + + constructor(private fb: FormBuilder, + private translate: TranslateService) { + super(); + for (const key of dataToFetchTranslations.keys()) { + if (key !== DataToFetch.FIELDS) { + this.fetchToData.push({ + value: key, + name: this.translate.instant(dataToFetchTranslations.get(key as DataToFetch)) + }); + } + } + } + + protected configForm(): FormGroup { + return this.tenantAttributesConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + let dataToFetch: DataToFetch; + if (isDefinedAndNotNull(configuration?.telemetry)) { + dataToFetch = configuration.telemetry ? DataToFetch.LATEST_TELEMETRY : DataToFetch.ATTRIBUTES; + } else { + dataToFetch = isDefinedAndNotNull(configuration?.dataToFetch) ? configuration.dataToFetch : DataToFetch.ATTRIBUTES; + } + + let dataMapping; + if (isDefinedAndNotNull(configuration?.attrMapping)) { + dataMapping = configuration.attrMapping; + } else { + dataMapping = isDefinedAndNotNull(configuration?.dataMapping) ? configuration.dataMapping : null; + } + + return { + dataToFetch, + dataMapping, + fetchTo: isDefinedAndNotNull(configuration?.fetchTo) ? configuration.fetchTo : FetchTo.METADATA + }; + } + + public selectTranslation(latestTelemetryTranslation: string, attributesTranslation: string) { + if (this.tenantAttributesConfigForm.get('dataToFetch').value === DataToFetch.LATEST_TELEMETRY) { + return latestTelemetryTranslation; + } else { + return attributesTranslation; + } + } + + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.tenantAttributesConfigForm = this.fb.group({ + dataToFetch: [configuration.dataToFetch, []], + dataMapping: [configuration.dataMapping, [Validators.required]], + fetchTo: [configuration.fetchTo, []] + }); + } + + protected readonly DataToFetch = DataToFetch; +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.html new file mode 100644 index 0000000000..44fe7d2ebd --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.html @@ -0,0 +1,122 @@ + +
    + + tb.rulenode.topic + + + {{ 'tb.rulenode.topic-required' | translate }} + + tb.rulenode.general-pattern-hint + + + tb.rulenode.hostname + + + {{ 'tb.rulenode.hostname-required' | translate }} + + + + tb.rulenode.device-id + + + {{ 'tb.rulenode.device-id-required' | translate }} + + + + + + tb.rulenode.credentials + + {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get('credentials.type').value) | translate }} + + +
    + + tb.rulenode.credentials-type + + + {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }} + + + + {{ 'tb.rulenode.credentials-type-required' | translate }} + + +
    + + + + + tb.rulenode.sas-key + + + + {{ 'tb.rulenode.sas-key-required' | translate }} + + + + + + + + + + + + + + tb.rulenode.private-key-password + + + + +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts new file mode 100644 index 0000000000..72864610f5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts @@ -0,0 +1,117 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { + AzureIotHubCredentialsType, + azureIotHubCredentialsTypes, + azureIotHubCredentialsTypeTranslations +} from '@home/components/rule-node/rule-node-config.models'; + +@Component({ + selector: 'tb-external-node-azure-iot-hub-config', + templateUrl: './azure-iot-hub-config.component.html', + styleUrls: ['./mqtt-config.component.scss'] +}) +export class AzureIotHubConfigComponent extends RuleNodeConfigurationComponent { + + azureIotHubConfigForm: UntypedFormGroup; + + allAzureIotHubCredentialsTypes = azureIotHubCredentialsTypes; + azureIotHubCredentialsTypeTranslationsMap = azureIotHubCredentialsTypeTranslations; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.azureIotHubConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.azureIotHubConfigForm = this.fb.group({ + topicPattern: [configuration ? configuration.topicPattern : null, [Validators.required]], + host: [configuration ? configuration.host : null, [Validators.required]], + port: [configuration ? configuration.port : null, [Validators.required, Validators.min(1), Validators.max(65535)]], + connectTimeoutSec: [configuration ? configuration.connectTimeoutSec : null, + [Validators.required, Validators.min(1), Validators.max(200)]], + clientId: [configuration ? configuration.clientId : null, [Validators.required]], + cleanSession: [configuration ? configuration.cleanSession : false, []], + ssl: [configuration ? configuration.ssl : false, []], + credentials: this.fb.group( + { + type: [configuration && configuration.credentials ? configuration.credentials.type : null, [Validators.required]], + sasKey: [configuration && configuration.credentials ? configuration.credentials.sasKey : null, []], + caCert: [configuration && configuration.credentials ? configuration.credentials.caCert : null, []], + caCertFileName: [configuration && configuration.credentials ? configuration.credentials.caCertFileName : null, []], + privateKey: [configuration && configuration.credentials ? configuration.credentials.privateKey : null, []], + privateKeyFileName: [configuration && configuration.credentials ? configuration.credentials.privateKeyFileName : null, []], + cert: [configuration && configuration.credentials ? configuration.credentials.cert : null, []], + certFileName: [configuration && configuration.credentials ? configuration.credentials.certFileName : null, []], + password: [configuration && configuration.credentials ? configuration.credentials.password : null, []], + } + ) + }); + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + const credentialsType: AzureIotHubCredentialsType = configuration.credentials.type; + if (credentialsType === 'sas') { + configuration.credentials = { + type: credentialsType, + sasKey: configuration.credentials.sasKey, + caCert: configuration.credentials.caCert, + caCertFileName: configuration.credentials.caCertFileName + }; + } + return configuration; + } + + protected validatorTriggers(): string[] { + return ['credentials.type']; + } + + protected updateValidators(emitEvent: boolean) { + const credentialsControl = this.azureIotHubConfigForm.get('credentials'); + const credentialsType: AzureIotHubCredentialsType = credentialsControl.get('type').value; + if (emitEvent) { + credentialsControl.reset({ type: credentialsType }, {emitEvent: false}); + } + credentialsControl.get('sasKey').setValidators([]); + credentialsControl.get('privateKey').setValidators([]); + credentialsControl.get('privateKeyFileName').setValidators([]); + credentialsControl.get('cert').setValidators([]); + credentialsControl.get('certFileName').setValidators([]); + switch (credentialsType) { + case 'sas': + credentialsControl.get('sasKey').setValidators([Validators.required]); + break; + case 'cert.PEM': + credentialsControl.get('privateKey').setValidators([Validators.required]); + credentialsControl.get('privateKeyFileName').setValidators([Validators.required]); + credentialsControl.get('cert').setValidators([Validators.required]); + credentialsControl.get('certFileName').setValidators([Validators.required]); + break; + } + credentialsControl.get('sasKey').updateValueAndValidity({emitEvent}); + credentialsControl.get('privateKey').updateValueAndValidity({emitEvent}); + credentialsControl.get('privateKeyFileName').updateValueAndValidity({emitEvent}); + credentialsControl.get('cert').updateValueAndValidity({emitEvent}); + credentialsControl.get('certFileName').updateValueAndValidity({emitEvent}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.html new file mode 100644 index 0000000000..6bb1438a00 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.html @@ -0,0 +1,111 @@ + +
    + + tb.rulenode.topic-pattern + + + {{ 'tb.rulenode.topic-pattern-required' | translate }} + + tb.rulenode.general-pattern-hint + + + tb.rulenode.key-pattern + + tb.rulenode.general-pattern-hint + +
    tb.rulenode.key-pattern-hint
    + + tb.rulenode.bootstrap-servers + + + {{ 'tb.rulenode.bootstrap-servers-required' | translate }} + + + + tb.rulenode.retries + + + {{ 'tb.rulenode.min-retries-message' | translate }} + + + + tb.rulenode.batch-size-bytes + + + {{ 'tb.rulenode.min-batch-size-bytes-message' | translate }} + + + + tb.rulenode.linger-ms + + + {{ 'tb.rulenode.min-linger-ms-message' | translate }} + + + + tb.rulenode.buffer-memory-bytes + + + {{ 'tb.rulenode.min-buffer-memory-bytes-message' | translate }} + + + + tb.rulenode.acks + + + {{ ackValue }} + + + + + tb.rulenode.key-serializer + + + {{ 'tb.rulenode.key-serializer-required' | translate }} + + + + tb.rulenode.value-serializer + + + {{ 'tb.rulenode.value-serializer-required' | translate }} + + + + + + + {{ 'tb.rulenode.add-metadata-key-values-as-kafka-headers' | translate }} + +
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    + + tb.rulenode.charset-encoding + + + {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }} + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.ts new file mode 100644 index 0000000000..d0f97a8f9d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.ts @@ -0,0 +1,79 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { + ToByteStandartCharsetTypes, + ToByteStandartCharsetTypeTranslations +} from '@home/components/rule-node/rule-node-config.models'; + +@Component({ + selector: 'tb-external-node-kafka-config', + templateUrl: './kafka-config.component.html', + styleUrls: [] +}) +export class KafkaConfigComponent extends RuleNodeConfigurationComponent { + + kafkaConfigForm: UntypedFormGroup; + + ackValues: string[] = ['all', '-1', '0', '1']; + + ToByteStandartCharsetTypesValues = ToByteStandartCharsetTypes; + ToByteStandartCharsetTypeTranslationMap = ToByteStandartCharsetTypeTranslations; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.kafkaConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.kafkaConfigForm = this.fb.group({ + topicPattern: [configuration ? configuration.topicPattern : null, [Validators.required]], + keyPattern: [configuration ? configuration.keyPattern : null], + bootstrapServers: [configuration ? configuration.bootstrapServers : null, [Validators.required]], + retries: [configuration ? configuration.retries : null, [Validators.min(0)]], + batchSize: [configuration ? configuration.batchSize : null, [Validators.min(0)]], + linger: [configuration ? configuration.linger : null, [Validators.min(0)]], + bufferMemory: [configuration ? configuration.bufferMemory : null, [Validators.min(0)]], + acks: [configuration ? configuration.acks : null, [Validators.required]], + keySerializer: [configuration ? configuration.keySerializer : null, [Validators.required]], + valueSerializer: [configuration ? configuration.valueSerializer : null, [Validators.required]], + otherProperties: [configuration ? configuration.otherProperties : null, []], + addMetadataKeyValuesAsKafkaHeaders: [configuration ? configuration.addMetadataKeyValuesAsKafkaHeaders : false, []], + kafkaHeadersCharset: [configuration ? configuration.kafkaHeadersCharset : null, []] + }); + } + + protected validatorTriggers(): string[] { + return ['addMetadataKeyValuesAsKafkaHeaders']; + } + + protected updateValidators(emitEvent: boolean) { + const addMetadataKeyValuesAsKafkaHeaders: boolean = this.kafkaConfigForm.get('addMetadataKeyValuesAsKafkaHeaders').value; + if (addMetadataKeyValuesAsKafkaHeaders) { + this.kafkaConfigForm.get('kafkaHeadersCharset').setValidators([Validators.required]); + } else { + this.kafkaConfigForm.get('kafkaHeadersCharset').setValidators([]); + } + this.kafkaConfigForm.get('kafkaHeadersCharset').updateValueAndValidity({emitEvent}); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.html new file mode 100644 index 0000000000..a6907082fc --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.html @@ -0,0 +1,115 @@ + +
    +
    +
    +
    tb.rulenode.function-configuration
    +
    + + +
    + + {{'tb.rulenode.function-name' | translate}} + + + {{'tb.rulenode.function-name-required' | translate}} + + + + {{'tb.rulenode.qualifier' | translate}} + + tb.rulenode.qualifier-hint + +
    +
    + +
    + + + tb.rulenode.aws-credentials + +
    + + tb.rulenode.aws-access-key-id + + + {{ 'tb.rulenode.aws-access-key-id-required' | translate }} + + + + tb.rulenode.aws-secret-access-key + + + {{ 'tb.rulenode.aws-secret-access-key-required' | translate }} + + + + tb.rulenode.aws-region + + + {{ 'tb.rulenode.aws-region-required' | translate }} + + +
    +
    +
    +
    + + + tb.rulenode.advanced-settings + +
    +
    + + tb.rulenode.connection-timeout + + + {{ 'tb.rulenode.connection-timeout-required' | translate }} + + + {{ 'tb.rulenode.connection-timeout-min' | translate }} + + help + + + tb.rulenode.request-timeout + + + {{ 'tb.rulenode.request-timeout-required' | translate }} + + + {{ 'tb.rulenode.request-timeout-min' | translate }} + + help + +
    +
    + + {{ 'tb.rulenode.tell-failure-aws-lambda' | translate }} + +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.ts new file mode 100644 index 0000000000..3270e3b51e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.ts @@ -0,0 +1,50 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-external-node-lambda-config', + templateUrl: './lambda-config.component.html', + styleUrls: [] +}) +export class LambdaConfigComponent extends RuleNodeConfigurationComponent { + + lambdaConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.lambdaConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.lambdaConfigForm = this.fb.group({ + functionName: [configuration ? configuration.functionName : null, [Validators.required]], + qualifier: [configuration ? configuration.qualifier : null, []], + accessKey: [configuration ? configuration.accessKey : null, [Validators.required]], + secretKey: [configuration ? configuration.secretKey : null, [Validators.required]], + region: [configuration ? configuration.region : null, [Validators.required]], + connectionTimeout: [configuration ? configuration.connectionTimeout : null, [Validators.required, Validators.min(0)]], + requestTimeout: [configuration ? configuration.requestTimeout : null, [Validators.required, Validators.min(0)]], + tellFailureIfFuncThrowsExc: [configuration ? configuration.tellFailureIfFuncThrowsExc : false, []] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html new file mode 100644 index 0000000000..989a8829b7 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html @@ -0,0 +1,85 @@ + +
    + + tb.rulenode.topic-pattern + + + {{ 'tb.rulenode.topic-pattern-required' | translate }} + + tb.rulenode.general-pattern-hint + +
    + + tb.rulenode.host + + + {{ 'tb.rulenode.host-required' | translate }} + + + + tb.rulenode.port + + + {{ 'tb.rulenode.port-required' | translate }} + + + {{ 'tb.rulenode.port-range' | translate }} + + + {{ 'tb.rulenode.port-range' | translate }} + + + + tb.rulenode.connect-timeout + + + {{ 'tb.rulenode.connect-timeout-required' | translate }} + + + {{ 'tb.rulenode.connect-timeout-range' | translate }} + + + {{ 'tb.rulenode.connect-timeout-range' | translate }} + + +
    + + tb.rulenode.client-id + + {{'tb.rulenode.client-id-hint' | translate}} + + + {{ 'tb.rulenode.append-client-id-suffix' | translate }} + +
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    + + {{ 'tb.rulenode.parse-to-plain-text' | translate }} + +
    {{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
    + + {{ 'tb.rulenode.clean-session' | translate }} + + + {{ "tb.rulenode.retained-message" | translate }} + + + {{ 'tb.rulenode.enable-ssl' | translate }} + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.scss new file mode 100644 index 0000000000..0bd9d8e62c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.scss @@ -0,0 +1,20 @@ +/** + * 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 { + .tb-mqtt-credentials-panel-group { + margin: 0 6px; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts new file mode 100644 index 0000000000..7edfc6f14d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts @@ -0,0 +1,71 @@ +/// +/// 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 { isNotEmptyStr } from '@core/public-api'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-external-node-mqtt-config', + templateUrl: './mqtt-config.component.html', + styleUrls: ['./mqtt-config.component.scss'] +}) +export class MqttConfigComponent extends RuleNodeConfigurationComponent { + + mqttConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.mqttConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.mqttConfigForm = this.fb.group({ + topicPattern: [configuration ? configuration.topicPattern : null, [Validators.required]], + host: [configuration ? configuration.host : null, [Validators.required]], + port: [configuration ? configuration.port : null, [Validators.required, Validators.min(1), Validators.max(65535)]], + connectTimeoutSec: [configuration ? configuration.connectTimeoutSec : null, + [Validators.required, Validators.min(1), Validators.max(200)]], + clientId: [configuration ? configuration.clientId : null, []], + appendClientIdSuffix: [{ + value: configuration ? configuration.appendClientIdSuffix : false, + disabled: !(configuration && isNotEmptyStr(configuration.clientId)) + }, []], + parseToPlainText: [configuration ? configuration.parseToPlainText : false, []], + cleanSession: [configuration ? configuration.cleanSession : false, []], + retainedMessage: [configuration ? configuration.retainedMessage : false, []], + ssl: [configuration ? configuration.ssl : false, []], + credentials: [configuration ? configuration.credentials : null, []] + }); + } + + protected updateValidators(emitEvent: boolean) { + if (isNotEmptyStr(this.mqttConfigForm.get('clientId').value)) { + this.mqttConfigForm.get('appendClientIdSuffix').enable({emitEvent: false}); + } else { + this.mqttConfigForm.get('appendClientIdSuffix').disable({emitEvent: false}); + } + this.mqttConfigForm.get('appendClientIdSuffix').updateValueAndValidity({emitEvent}); + } + + protected validatorTriggers(): string[] { + return ['clientId']; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.html new file mode 100644 index 0000000000..ee031b1237 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.html @@ -0,0 +1,34 @@ + +
    + + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.ts new file mode 100644 index 0000000000..2b2fcfb319 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/notification-config.component.ts @@ -0,0 +1,48 @@ +/// +/// 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 { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { NotificationType } from '@shared/models/notification.models'; +import { EntityType } from '@shared/models/entity-type.models'; + +@Component({ + selector: 'tb-external-node-notification-config', + templateUrl: './notification-config.component.html', + styleUrls: [] +}) +export class NotificationConfigComponent extends RuleNodeConfigurationComponent { + + notificationConfigForm: FormGroup; + notificationType = NotificationType; + entityType = EntityType; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.notificationConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.notificationConfigForm = this.fb.group({ + templateId: [configuration ? configuration.templateId : null, [Validators.required]], + targets: [configuration ? configuration.targets : [], [Validators.required]], + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.html new file mode 100644 index 0000000000..eb5c700400 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.html @@ -0,0 +1,53 @@ + +
    + + tb.rulenode.gcp-project-id + + + {{ 'tb.rulenode.gcp-project-id-required' | translate }} + + + + tb.rulenode.pubsub-topic-name + + + {{ 'tb.rulenode.pubsub-topic-name-required' | translate }} + + + + + +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.ts new file mode 100644 index 0000000000..f7c65537e0 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-external-node-pub-sub-config', + templateUrl: './pubsub-config.component.html', + styleUrls: [] +}) +export class PubSubConfigComponent extends RuleNodeConfigurationComponent { + + pubSubConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.pubSubConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.pubSubConfigForm = this.fb.group({ + projectId: [configuration ? configuration.projectId : null, [Validators.required]], + topicName: [configuration ? configuration.topicName : null, [Validators.required]], + serviceAccountKey: [configuration ? configuration.serviceAccountKey : null, [Validators.required]], + serviceAccountKeyFileName: [configuration ? configuration.serviceAccountKeyFileName : null, [Validators.required]], + messageAttributes: [configuration ? configuration.messageAttributes : null, []] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.html new file mode 100644 index 0000000000..0ef6b40877 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.html @@ -0,0 +1,96 @@ + +
    + + tb.rulenode.exchange-name-pattern + + + + tb.rulenode.routing-key-pattern + + + + tb.rulenode.message-properties + + + {{ property }} + + + +
    + + tb.rulenode.host + + + {{ 'tb.rulenode.host-required' | translate }} + + + + tb.rulenode.port + + + {{ 'tb.rulenode.port-required' | translate }} + + + {{ 'tb.rulenode.port-range' | translate }} + + + {{ 'tb.rulenode.port-range' | translate }} + + +
    + + tb.rulenode.virtual-host + + + + tb.rulenode.username + + + + tb.rulenode.password + + + + + {{ 'tb.rulenode.automatic-recovery' | translate }} + + + tb.rulenode.connection-timeout-ms + + + {{ 'tb.rulenode.min-connection-timeout-ms-message' | translate }} + + + + tb.rulenode.handshake-timeout-ms + + + {{ 'tb.rulenode.min-handshake-timeout-ms-message' | translate }} + + + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.ts new file mode 100644 index 0000000000..89558bbe7f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.ts @@ -0,0 +1,64 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-external-node-rabbit-mq-config', + templateUrl: './rabbit-mq-config.component.html', + styleUrls: [] +}) +export class RabbitMqConfigComponent extends RuleNodeConfigurationComponent { + + rabbitMqConfigForm: UntypedFormGroup; + + messageProperties: string[] = [ + null, + 'BASIC', + 'TEXT_PLAIN', + 'MINIMAL_BASIC', + 'MINIMAL_PERSISTENT_BASIC', + 'PERSISTENT_BASIC', + 'PERSISTENT_TEXT_PLAIN' + ]; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.rabbitMqConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.rabbitMqConfigForm = this.fb.group({ + exchangeNamePattern: [configuration ? configuration.exchangeNamePattern : null, []], + routingKeyPattern: [configuration ? configuration.routingKeyPattern : null, []], + messageProperties: [configuration ? configuration.messageProperties : null, []], + host: [configuration ? configuration.host : null, [Validators.required]], + port: [configuration ? configuration.port : null, [Validators.required, Validators.min(1), Validators.max(65535)]], + virtualHost: [configuration ? configuration.virtualHost : null, []], + username: [configuration ? configuration.username : null, []], + password: [configuration ? configuration.password : null, []], + automaticRecoveryEnabled: [configuration ? configuration.automaticRecoveryEnabled : false, []], + connectionTimeout: [configuration ? configuration.connectionTimeout : null, [Validators.min(0)]], + handshakeTimeout: [configuration ? configuration.handshakeTimeout : null, [Validators.min(0)]], + clientProperties: [configuration ? configuration.clientProperties : null, []] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html new file mode 100644 index 0000000000..5dfca5144a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html @@ -0,0 +1,130 @@ + +
    + + tb.rulenode.endpoint-url-pattern + + + {{ 'tb.rulenode.endpoint-url-pattern-required' | translate }} + + tb.rulenode.general-pattern-hint + + + tb.rulenode.request-method + + + {{ requestType }} + + + + + {{ 'tb.rulenode.enable-proxy' | translate }} + + + {{ 'tb.rulenode.use-simple-client-http-factory' | translate }} + + + {{ 'tb.rulenode.parse-to-plain-text' | translate }} + +
    tb.rulenode.parse-to-plain-text-hint
    + + {{ 'tb.rulenode.ignore-request-body' | translate }} + +
    + + {{ 'tb.rulenode.use-system-proxy-properties' | translate }} + +
    +
    + + tb.rulenode.proxy-scheme + + + {{ proxyScheme }} + + + + + tb.rulenode.proxy-host + + + {{ 'tb.rulenode.proxy-host-required' | translate }} + + + + tb.rulenode.proxy-port + + + {{ 'tb.rulenode.proxy-port-required' | translate }} + + + {{ 'tb.rulenode.proxy-port-range' | translate }} + + +
    + + tb.rulenode.proxy-user + + + + tb.rulenode.proxy-password + + +
    +
    + + tb.rulenode.read-timeout + + tb.rulenode.read-timeout-hint + + {{ 'tb.rulenode.int-range' | translate }} + + + + tb.rulenode.max-parallel-requests-count + + tb.rulenode.max-parallel-requests-count-hint + + {{ 'tb.rulenode.int-range' | translate }} + + + + tb.rulenode.max-response-size + + tb.rulenode.max-response-size-hint + + {{ 'tb.rulenode.memory-buffer-size-range' | translate: { max: MemoryBufferSizeInKbLimit } }} + + + +
    + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.ts new file mode 100644 index 0000000000..fc6583c096 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.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 { Component } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { HttpRequestType, IntLimit } from '../rule-node-config.models'; + +@Component({ + selector: 'tb-external-node-rest-api-call-config', + templateUrl: './rest-api-call-config.component.html', + styleUrls: [] +}) +export class RestApiCallConfigComponent extends RuleNodeConfigurationComponent { + + restApiCallConfigForm: UntypedFormGroup; + + readonly proxySchemes: string[] = ['http', 'https']; + readonly httpRequestTypes = Object.keys(HttpRequestType); + readonly MemoryBufferSizeInKbLimit = 25000; + readonly IntLimit = IntLimit; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.restApiCallConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.restApiCallConfigForm = this.fb.group({ + restEndpointUrlPattern: [configuration ? configuration.restEndpointUrlPattern : null, [Validators.required]], + requestMethod: [configuration ? configuration.requestMethod : null, [Validators.required]], + useSimpleClientHttpFactory: [configuration ? configuration.useSimpleClientHttpFactory : false, []], + parseToPlainText: [configuration ? configuration.parseToPlainText : false, []], + ignoreRequestBody: [configuration ? configuration.ignoreRequestBody : false, []], + enableProxy: [configuration ? configuration.enableProxy : false, []], + useSystemProxyProperties: [configuration ? configuration.enableProxy : false, []], + proxyScheme: [configuration ? configuration.proxyHost : null, []], + proxyHost: [configuration ? configuration.proxyHost : null, []], + proxyPort: [configuration ? configuration.proxyPort : null, []], + proxyUser: [configuration ? configuration.proxyUser :null, []], + proxyPassword: [configuration ? configuration.proxyPassword :null, []], + readTimeoutMs: [configuration ? configuration.readTimeoutMs : null, [Validators.min(0), Validators.max(IntLimit)]], + maxParallelRequestsCount: [configuration ? configuration.maxParallelRequestsCount : null, [Validators.min(0), Validators.max(IntLimit)]], + headers: [configuration ? configuration.headers : null, []], + credentials: [configuration ? configuration.credentials : null, []], + maxInMemoryBufferSizeInKb: [configuration ? configuration.maxInMemoryBufferSizeInKb : null, [Validators.min(1), Validators.max(this.MemoryBufferSizeInKbLimit)]] + }); + } + + protected validatorTriggers(): string[] { + return ['useSimpleClientHttpFactory', 'enableProxy', 'useSystemProxyProperties']; + } + + protected updateValidators(emitEvent: boolean) { + const useSimpleClientHttpFactory: boolean = this.restApiCallConfigForm.get('useSimpleClientHttpFactory').value; + const enableProxy: boolean = this.restApiCallConfigForm.get('enableProxy').value; + const useSystemProxyProperties: boolean = this.restApiCallConfigForm.get('useSystemProxyProperties').value; + + if (enableProxy && !useSystemProxyProperties) { + this.restApiCallConfigForm.get('proxyHost').setValidators(enableProxy ? [Validators.required] : []); + this.restApiCallConfigForm.get('proxyPort').setValidators(enableProxy ? + [Validators.required, Validators.min(1), Validators.max(65535)] : []); + } else { + this.restApiCallConfigForm.get('proxyHost').setValidators([]); + this.restApiCallConfigForm.get('proxyPort').setValidators([]); + + if (useSimpleClientHttpFactory) { + this.restApiCallConfigForm.get('readTimeoutMs').setValidators([]); + } else { + this.restApiCallConfigForm.get('readTimeoutMs').setValidators([Validators.min(0), Validators.max(IntLimit)]); + } + } + + this.restApiCallConfigForm.get('readTimeoutMs').updateValueAndValidity({emitEvent}); + this.restApiCallConfigForm.get('proxyHost').updateValueAndValidity({emitEvent}); + this.restApiCallConfigForm.get('proxyPort').updateValueAndValidity({emitEvent}); + this.restApiCallConfigForm.get('credentials').updateValueAndValidity({emitEvent}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rule-node-config-external.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/rule-node-config-external.module.ts new file mode 100644 index 0000000000..c170d9ccd6 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rule-node-config-external.module.ts @@ -0,0 +1,91 @@ +/// +/// 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 { NgModule, Type } from '@angular/core'; +import { SnsConfigComponent } from './sns-config.component'; +import { SqsConfigComponent } from './sqs-config.component'; +import { PubSubConfigComponent } from './pubsub-config.component'; +import { KafkaConfigComponent } from './kafka-config.component'; +import { MqttConfigComponent } from './mqtt-config.component'; +import { NotificationConfigComponent } from './notification-config.component'; +import { RabbitMqConfigComponent } from './rabbit-mq-config.component'; +import { RestApiCallConfigComponent } from './rest-api-call-config.component'; +import { SendEmailConfigComponent } from './send-email-config.component'; +import { AzureIotHubConfigComponent } from './azure-iot-hub-config.component'; +import { SendSmsConfigComponent } from './send-sms-config.component'; +import { CommonModule } from '@angular/common'; +import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { HomeComponentsModule } from '@home/components/public-api'; +import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.module'; +import { SlackConfigComponent } from './slack-config.component'; +import { LambdaConfigComponent } from './lambda-config.component'; + +@NgModule({ + declarations: [ + SnsConfigComponent, + SqsConfigComponent, + LambdaConfigComponent, + PubSubConfigComponent, + KafkaConfigComponent, + MqttConfigComponent, + NotificationConfigComponent, + RabbitMqConfigComponent, + RestApiCallConfigComponent, + SendEmailConfigComponent, + AzureIotHubConfigComponent, + SendSmsConfigComponent, + SlackConfigComponent + ], + imports: [ + CommonModule, + SharedModule, + HomeComponentsModule, + RuleNodeConfigCommonModule + ], + exports: [ + SnsConfigComponent, + SqsConfigComponent, + LambdaConfigComponent, + PubSubConfigComponent, + KafkaConfigComponent, + MqttConfigComponent, + NotificationConfigComponent, + RabbitMqConfigComponent, + RestApiCallConfigComponent, + SendEmailConfigComponent, + AzureIotHubConfigComponent, + SendSmsConfigComponent, + SlackConfigComponent + ] +}) +export class RuleNodeConfigExternalModule { +} + +export const ruleNodeExternalConfigComponentsMap: Record> = { + 'tbExternalNodeAzureIotHubConfig': AzureIotHubConfigComponent, + 'tbExternalNodeKafkaConfig': KafkaConfigComponent, + 'tbExternalNodeLambdaConfig': LambdaConfigComponent, + 'tbExternalNodeMqttConfig': MqttConfigComponent, + 'tbExternalNodeNotificationConfig': NotificationConfigComponent, + 'tbExternalNodePubSubConfig': PubSubConfigComponent, + 'tbExternalNodeRabbitMqConfig': RabbitMqConfigComponent, + 'tbExternalNodeRestApiCallConfig': RestApiCallConfigComponent, + 'tbExternalNodeSendEmailConfig': SendEmailConfigComponent, + 'tbExternalNodeSendSmsConfig': SendSmsConfigComponent, + 'tbExternalNodeSlackConfig': SlackConfigComponent, + 'tbExternalNodeSnsConfig': SnsConfigComponent, + 'tbExternalNodeSqsConfig': SqsConfigComponent +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.html new file mode 100644 index 0000000000..cbc4ec7a4a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.html @@ -0,0 +1,116 @@ + +
    + + {{ 'tb.rulenode.use-system-smtp-settings' | translate }} + +
    + + tb.rulenode.smtp-protocol + + + {{ smtpProtocol.toUpperCase() }} + + + +
    + + tb.rulenode.smtp-host + + + {{ 'tb.rulenode.smtp-host-required' | translate }} + + + + tb.rulenode.smtp-port + + + {{ 'tb.rulenode.smtp-port-required' | translate }} + + + {{ 'tb.rulenode.smtp-port-range' | translate }} + + + {{ 'tb.rulenode.smtp-port-range' | translate }} + + +
    + + tb.rulenode.timeout-msec + + + {{ 'tb.rulenode.timeout-required' | translate }} + + + {{ 'tb.rulenode.min-timeout-msec-message' | translate }} + + + + {{ 'tb.rulenode.enable-tls' | translate }} + + + tb.rulenode.tls-version + + + {{ tlsVersion }} + + + + + {{ 'tb.rulenode.enable-proxy' | translate }} + +
    +
    + + tb.rulenode.proxy-host + + + {{ 'tb.rulenode.proxy-host-required' | translate }} + + + + tb.rulenode.proxy-port + + + {{ 'tb.rulenode.proxy-port-required' | translate }} + + + {{ 'tb.rulenode.proxy-port-range' | translate }} + + +
    + + tb.rulenode.proxy-user + + + + tb.rulenode.proxy-password + + +
    + + tb.rulenode.username + + + + tb.rulenode.password + + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.ts new file mode 100644 index 0000000000..b0e77d6649 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.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 { Component } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-external-node-send-email-config', + templateUrl: './send-email-config.component.html', + styleUrls: [] +}) +export class SendEmailConfigComponent extends RuleNodeConfigurationComponent { + + sendEmailConfigForm: UntypedFormGroup; + + smtpProtocols: string[] = [ + 'smtp', + 'smtps' + ]; + + tlsVersions = ['TLSv1', 'TLSv1.1', 'TLSv1.2', 'TLSv1.3']; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.sendEmailConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.sendEmailConfigForm = this.fb.group({ + useSystemSmtpSettings: [configuration ? configuration.useSystemSmtpSettings : false, []], + smtpProtocol: [configuration ? configuration.smtpProtocol : null, []], + smtpHost: [configuration ? configuration.smtpHost : null, []], + smtpPort: [configuration ? configuration.smtpPort : null, []], + timeout: [configuration ? configuration.timeout : null, []], + enableTls: [configuration ? configuration.enableTls : false, []], + tlsVersion: [configuration ? configuration.tlsVersion : null, []], + enableProxy: [configuration ? configuration.enableProxy : false, []], + proxyHost: [configuration ? configuration.proxyHost : null, []], + proxyPort: [configuration ? configuration.proxyPort : null, []], + proxyUser: [configuration ? configuration.proxyUser :null, []], + proxyPassword: [configuration ? configuration.proxyPassword :null, []], + username: [configuration ? configuration.username : null, []], + password: [configuration ? configuration.password : null, []] + }); + } + + protected validatorTriggers(): string[] { + return ['useSystemSmtpSettings', 'enableProxy']; + } + + protected updateValidators(emitEvent: boolean) { + const useSystemSmtpSettings: boolean = this.sendEmailConfigForm.get('useSystemSmtpSettings').value; + const enableProxy: boolean = this.sendEmailConfigForm.get('enableProxy').value; + if (useSystemSmtpSettings) { + 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([]); + } else { + this.sendEmailConfigForm.get('smtpProtocol').setValidators([Validators.required]); + this.sendEmailConfigForm.get('smtpHost').setValidators([Validators.required]); + this.sendEmailConfigForm.get('smtpPort').setValidators([Validators.required, Validators.min(1), Validators.max(65535)]); + this.sendEmailConfigForm.get('timeout').setValidators([Validators.required, Validators.min(0)]); + this.sendEmailConfigForm.get('proxyHost').setValidators(enableProxy ? [Validators.required] : []); + this.sendEmailConfigForm.get('proxyPort').setValidators(enableProxy ? + [Validators.required, Validators.min(1), Validators.max(65535)] : []); + } + this.sendEmailConfigForm.get('smtpProtocol').updateValueAndValidity({emitEvent}); + this.sendEmailConfigForm.get('smtpHost').updateValueAndValidity({emitEvent}); + this.sendEmailConfigForm.get('smtpPort').updateValueAndValidity({emitEvent}); + this.sendEmailConfigForm.get('timeout').updateValueAndValidity({emitEvent}); + this.sendEmailConfigForm.get('proxyHost').updateValueAndValidity({emitEvent}); + this.sendEmailConfigForm.get('proxyPort').updateValueAndValidity({emitEvent}); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.html new file mode 100644 index 0000000000..12f9208c5d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.html @@ -0,0 +1,43 @@ + +
    + + tb.rulenode.numbers-to-template + + + {{ 'tb.rulenode.numbers-to-template-required' | translate }} + + + + + tb.rulenode.sms-message-template + + + {{ 'tb.rulenode.sms-message-template-required' | translate }} + + tb.rulenode.general-pattern-hint + + + {{ 'tb.rulenode.use-system-sms-settings' | translate }} + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.ts new file mode 100644 index 0000000000..aef2077e1c --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.ts @@ -0,0 +1,61 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-external-node-send-sms-config', + templateUrl: './send-sms-config.component.html', + styleUrls: [] +}) +export class SendSmsConfigComponent extends RuleNodeConfigurationComponent { + + sendSmsConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.sendSmsConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.sendSmsConfigForm = this.fb.group({ + numbersToTemplate: [configuration ? configuration.numbersToTemplate : null, [Validators.required]], + smsMessageTemplate: [configuration ? configuration.smsMessageTemplate : null, [Validators.required]], + useSystemSmsSettings: [configuration ? configuration.useSystemSmsSettings : false, []], + smsProviderConfiguration: [configuration ? configuration.smsProviderConfiguration : null, []], + }); + } + + protected validatorTriggers(): string[] { + return ['useSystemSmsSettings']; + } + + protected updateValidators(emitEvent: boolean) { + const useSystemSmsSettings: boolean = this.sendSmsConfigForm.get('useSystemSmsSettings').value; + if (useSystemSmsSettings) { + this.sendSmsConfigForm.get('smsProviderConfiguration').setValidators([]); + } else { + this.sendSmsConfigForm.get('smsProviderConfiguration').setValidators([Validators.required]); + } + this.sendSmsConfigForm.get('smsProviderConfiguration').updateValueAndValidity({emitEvent}); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.html new file mode 100644 index 0000000000..1a466f6bf9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.html @@ -0,0 +1,49 @@ + +
    + + tb.rulenode.message-template + + + {{ 'tb.rulenode.message-template-required' | translate }} + + tb.rulenode.general-pattern-hint + + + {{ 'tb.rulenode.use-system-slack-settings' | translate }} + + + tb.rulenode.slack-api-token + + + {{ 'tb.rulenode.slack-api-token-required' | translate }} + + + + + + {{ slackChanelTypesTranslateMap.get(slackChanelType) | translate }} + + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.scss new file mode 100644 index 0000000000..524b588874 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.scss @@ -0,0 +1,43 @@ +/** + * 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 { + .tb-title { + display: block; + padding-bottom: 6px; + } +} + +:host ::ng-deep { + .mat-mdc-radio-group { + display: flex; + flex-direction: row; + margin-bottom: 22px; + gap: 12px; + + .mat-mdc-radio-button { + flex: 1 1 100%; + padding: 4px; + border: 1px solid rgba(0, 0, 0, 0.12); + border-radius: 6px; + } + } + + @media screen and (max-width: 599px) { + .mat-mdc-radio-group { + flex-direction: column; + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.ts new file mode 100644 index 0000000000..4d8cfc7a32 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/slack-config.component.ts @@ -0,0 +1,64 @@ +/// +/// 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 { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, SlackChanelType, SlackChanelTypesTranslateMap } from '@app/shared/public-api'; +import { RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-external-node-slack-config', + templateUrl: './slack-config.component.html', + styleUrls: ['./slack-config.component.scss'] +}) +export class SlackConfigComponent extends RuleNodeConfigurationComponent { + + slackConfigForm: FormGroup; + slackChanelTypes = Object.keys(SlackChanelType) as SlackChanelType[]; + slackChanelTypesTranslateMap = SlackChanelTypesTranslateMap; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.slackConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.slackConfigForm = this.fb.group({ + botToken: [configuration ? configuration.botToken : null], + useSystemSettings: [configuration ? configuration.useSystemSettings : false], + messageTemplate: [configuration ? configuration.messageTemplate : null, [Validators.required]], + conversationType: [configuration ? configuration.conversationType : null, [Validators.required]], + conversation: [configuration ? configuration.conversation : null, [Validators.required]], + }); + } + + protected validatorTriggers(): string[] { + return ['useSystemSettings']; + } + + protected updateValidators(emitEvent: boolean) { + const useSystemSettings: boolean = this.slackConfigForm.get('useSystemSettings').value; + if (useSystemSettings) { + this.slackConfigForm.get('botToken').clearValidators(); + } else { + this.slackConfigForm.get('botToken').setValidators([Validators.required]); + } + this.slackConfigForm.get('botToken').updateValueAndValidity({emitEvent}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.html new file mode 100644 index 0000000000..f4e4aa738d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.html @@ -0,0 +1,48 @@ + +
    + + tb.rulenode.topic-arn-pattern + + + {{ 'tb.rulenode.topic-arn-pattern-required' | translate }} + + tb.rulenode.general-pattern-hint + + + tb.rulenode.aws-access-key-id + + + {{ 'tb.rulenode.aws-access-key-id-required' | translate }} + + + + tb.rulenode.aws-secret-access-key + + + {{ 'tb.rulenode.aws-secret-access-key-required' | translate }} + + + + tb.rulenode.aws-region + + + {{ 'tb.rulenode.aws-region-required' | translate }} + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.ts new file mode 100644 index 0000000000..9c2159c2a9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.ts @@ -0,0 +1,46 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-external-node-sns-config', + templateUrl: './sns-config.component.html', + styleUrls: [] +}) +export class SnsConfigComponent extends RuleNodeConfigurationComponent { + + snsConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.snsConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.snsConfigForm = this.fb.group({ + topicArnPattern: [configuration ? configuration.topicArnPattern : null, [Validators.required]], + accessKeyId: [configuration ? configuration.accessKeyId : null, [Validators.required]], + secretAccessKey: [configuration ? configuration.secretAccessKey : null, [Validators.required]], + region: [configuration ? configuration.region : null, [Validators.required]] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.html new file mode 100644 index 0000000000..a7272e6d66 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.html @@ -0,0 +1,76 @@ + +
    + + tb.rulenode.queue-type + + + {{ sqsQueueTypeTranslationsMap.get(type) | translate }} + + + + + tb.rulenode.queue-url-pattern + + + {{ 'tb.rulenode.queue-url-pattern-required' | translate }} + + tb.rulenode.general-pattern-hint + + + tb.rulenode.delay-seconds + + + {{ 'tb.rulenode.min-delay-seconds-message' | translate }} + + + {{ 'tb.rulenode.max-delay-seconds-message' | translate }} + + + +
    + + + + tb.rulenode.aws-access-key-id + + + {{ 'tb.rulenode.aws-access-key-id-required' | translate }} + + + + tb.rulenode.aws-secret-access-key + + + {{ 'tb.rulenode.aws-secret-access-key-required' | translate }} + + + + tb.rulenode.aws-region + + + {{ 'tb.rulenode.aws-region-required' | translate }} + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.ts new file mode 100644 index 0000000000..8e77682c4f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.ts @@ -0,0 +1,54 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { SqsQueueType, sqsQueueTypeTranslations } from '@home/components/rule-node/rule-node-config.models'; + +@Component({ + selector: 'tb-external-node-sqs-config', + templateUrl: './sqs-config.component.html', + styleUrls: [] +}) +export class SqsConfigComponent extends RuleNodeConfigurationComponent { + + sqsConfigForm: UntypedFormGroup; + + sqsQueueType = SqsQueueType; + sqsQueueTypes = Object.keys(SqsQueueType); + sqsQueueTypeTranslationsMap = sqsQueueTypeTranslations; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.sqsConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.sqsConfigForm = this.fb.group({ + queueType: [configuration ? configuration.queueType : null, [Validators.required]], + queueUrlPattern: [configuration ? configuration.queueUrlPattern : null, [Validators.required]], + delaySeconds: [configuration ? configuration.delaySeconds : null, [Validators.min(0), Validators.max(900)]], + messageAttributes: [configuration ? configuration.messageAttributes : null, []], + accessKeyId: [configuration ? configuration.accessKeyId : null, [Validators.required]], + secretAccessKey: [configuration ? configuration.secretAccessKey : null, [Validators.required]], + region: [configuration ? configuration.region : null, [Validators.required]] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.html new file mode 100644 index 0000000000..329b876e1e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.html @@ -0,0 +1,29 @@ + +
    +
    +
    tb.rulenode.alarm-status
    +
    + tb.rulenode.alarm-required +
    +
    + +
    + + + diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.ts new file mode 100644 index 0000000000..125fde1bd6 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.ts @@ -0,0 +1,52 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; + +@Component({ + selector: 'tb-filter-node-check-alarm-status-config', + templateUrl: './check-alarm-status.component.html', + styleUrls: [] +}) +export class CheckAlarmStatusComponent extends RuleNodeConfigurationComponent { + alarmStatusConfigForm: FormGroup; + + searchText = ''; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.alarmStatusConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + alarmStatusList: isDefinedAndNotNull(configuration?.alarmStatusList) ? configuration.alarmStatusList : null + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.alarmStatusConfigForm = this.fb.group({ + alarmStatusList: [configuration.alarmStatusList, [Validators.required]], + }); + } +} + diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.html new file mode 100644 index 0000000000..7ded71d798 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.html @@ -0,0 +1,45 @@ + +
    +
    +
    tb.rulenode.fields-to-check
    +
    + tb.rulenode.at-least-one-field-required +
    +
    + + help + + + help + +
    + + {{ 'tb.rulenode.check-all-keys' | translate }} + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.ts new file mode 100644 index 0000000000..2904c8eee2 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.ts @@ -0,0 +1,78 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; + +@Component({ + selector: 'tb-filter-node-check-message-config', + templateUrl: './check-message-config.component.html', + styleUrls: [] +}) +export class CheckMessageConfigComponent extends RuleNodeConfigurationComponent { + + checkMessageConfigForm: FormGroup; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.checkMessageConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + messageNames: isDefinedAndNotNull(configuration?.messageNames) ? configuration.messageNames : [], + metadataNames: isDefinedAndNotNull(configuration?.metadataNames) ? configuration.metadataNames : [], + checkAllKeys: isDefinedAndNotNull(configuration?.checkAllKeys) ? configuration.checkAllKeys : false + }; + } + + protected prepareOutputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + messageNames: isDefinedAndNotNull(configuration?.messageNames) ? configuration.messageNames : [], + metadataNames: isDefinedAndNotNull(configuration?.metadataNames) ? configuration.metadataNames : [], + checkAllKeys: configuration.checkAllKeys + }; + } + + + private atLeastOne(validator: ValidatorFn, controls: string[] = null) { + return (group: FormGroup): ValidationErrors | null => { + if (!controls) { + controls = Object.keys(group.controls); + } + const hasAtLeastOne = group?.controls && controls.some(k => !validator(group.controls[k])); + + return hasAtLeastOne ? null : {atLeastOne: true}; + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.checkMessageConfigForm = this.fb.group({ + messageNames: [configuration.messageNames, []], + metadataNames: [configuration.metadataNames, []], + checkAllKeys: [configuration.checkAllKeys, []] + }, {validators: this.atLeastOne(Validators.required, ['messageNames', 'metadataNames'])}); + } + + get touchedValidationControl(): boolean { + return ['messageNames', 'metadataNames'].some(name => this.checkMessageConfigForm.get(name).touched); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.html new file mode 100644 index 0000000000..2a4b61792e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.html @@ -0,0 +1,55 @@ + +
    +
    tb.rulenode.relation-search-parameters
    +
    + + {{ 'relation.direction' | translate }} + + + {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix + + + + + +
    + + {{ 'tb.rulenode.check-relation-to-specific-entity' | translate }} + +
    +
    + + + + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.scss new file mode 100644 index 0000000000..b61d0a5bb5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.scss @@ -0,0 +1,20 @@ +/** + * 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 { + .slide-toggle { + margin-bottom: 18px + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.ts new file mode 100644 index 0000000000..6c8a01050f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.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 { Component } from '@angular/core'; +import { isDefinedAndNotNull } from '@core/public-api'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { EntitySearchDirection, entitySearchDirectionTranslations } from '@app/shared/models/relation.models'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; + +@Component({ + selector: 'tb-filter-node-check-relation-config', + templateUrl: './check-relation-config.component.html', + styleUrls: ['./check-relation-config.component.scss'] +}) +export class CheckRelationConfigComponent extends RuleNodeConfigurationComponent { + + checkRelationConfigForm: UntypedFormGroup; + + entitySearchDirection: Array = Object.values(EntitySearchDirection); + entitySearchDirectionTranslationsMap = entitySearchDirectionTranslations; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.checkRelationConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + checkForSingleEntity: isDefinedAndNotNull(configuration?.checkForSingleEntity) ? configuration.checkForSingleEntity : false, + direction: isDefinedAndNotNull(configuration?.direction) ? configuration.direction : null, + entityType: isDefinedAndNotNull(configuration?.entityType) ? configuration.entityType : null, + entityId: isDefinedAndNotNull(configuration?.entityId) ? configuration.entityId : null, + relationType: isDefinedAndNotNull(configuration?.relationType) ? configuration.relationType : null + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.checkRelationConfigForm = this.fb.group({ + checkForSingleEntity: [configuration.checkForSingleEntity, []], + direction: [configuration.direction, []], + entityType: [configuration.entityType, + configuration && configuration.checkForSingleEntity ? [Validators.required] : []], + entityId: [configuration.entityId, + configuration && configuration.checkForSingleEntity ? [Validators.required] : []], + relationType: [configuration.relationType, [Validators.required]] + }); + } + + protected validatorTriggers(): string[] { + return ['checkForSingleEntity']; + } + + protected updateValidators(emitEvent: boolean) { + const checkForSingleEntity: boolean = this.checkRelationConfigForm.get('checkForSingleEntity').value; + this.checkRelationConfigForm.get('entityType').setValidators(checkForSingleEntity ? [Validators.required] : []); + this.checkRelationConfigForm.get('entityType').updateValueAndValidity({emitEvent}); + this.checkRelationConfigForm.get('entityId').setValidators(checkForSingleEntity ? [Validators.required] : []); + this.checkRelationConfigForm.get('entityId').updateValueAndValidity({emitEvent}); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.html new file mode 100644 index 0000000000..738e834450 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.html @@ -0,0 +1,126 @@ + +
    +
    +
    tb.rulenode.coordinate-field-names
    +
    +
    + + {{ 'tb.rulenode.latitude-field-name' | translate }} + + + {{ 'tb.rulenode.latitude-field-name-required' | translate }} + + + + {{ 'tb.rulenode.longitude-field-name' | translate }} + + + {{ 'tb.rulenode.longitude-field-name-required' | translate }} + + +
    +
    tb.rulenode.coordinate-field-hint
    +
    +
    +
    +
    tb.rulenode.geofence-configuration
    +
    + + {{ 'tb.rulenode.perimeter-type' | translate }} + + + {{ perimeterTypeTranslationMap.get(type) | translate }} + + + +
    + + {{ 'tb.rulenode.fetch-perimeter-info-from-metadata' | translate }} + +
    + + {{ 'tb.rulenode.perimeter-key-name' | translate }} + + + {{ 'tb.rulenode.perimeter-key-name-required' | translate }} + + {{ 'tb.rulenode.perimeter-key-name-hint' | translate }} + +
    +
    + + {{ 'tb.rulenode.circle-center-latitude' | translate }} + + + {{ 'tb.rulenode.circle-center-latitude-required' | translate }} + + + + {{ 'tb.rulenode.circle-center-longitude' | translate }} + + + {{ 'tb.rulenode.circle-center-longitude-required' | translate }} + + +
    +
    + + {{ 'tb.rulenode.range' | translate }} + + + {{ 'tb.rulenode.range-required' | translate }} + + + + {{ 'tb.rulenode.range-units' | translate }} + + + {{ rangeUnitTranslationMap.get(type) | translate }} + + + + {{ 'tb.rulenode.range-units-required' | translate }} + + +
    +
    + + {{ 'tb.rulenode.polygon-definition' | translate }} + + {{ 'tb.rulenode.polygon-definition-hint' | translate }} + + {{ 'tb.rulenode.polygon-definition-required' | translate }} + + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.scss new file mode 100644 index 0000000000..f177555e37 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.scss @@ -0,0 +1,20 @@ +/** + * 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 { + .slide-toggle { + margin-bottom: 18px; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.ts new file mode 100644 index 0000000000..6fb2158e7a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.ts @@ -0,0 +1,121 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { PerimeterType, perimeterTypeTranslations, RangeUnit, rangeUnitTranslations } from '../rule-node-config.models'; + +@Component({ + selector: 'tb-filter-node-gps-geofencing-config', + templateUrl: './gps-geo-filter-config.component.html', + styleUrls: ['./gps-geo-filter-config.component.scss'] +}) +export class GpsGeoFilterConfigComponent extends RuleNodeConfigurationComponent { + + geoFilterConfigForm: FormGroup; + + perimeterType = PerimeterType; + perimeterTypes: Array = Object.values(PerimeterType); + perimeterTypeTranslationMap = perimeterTypeTranslations; + + rangeUnits: Array = Object.values(RangeUnit); + rangeUnitTranslationMap = rangeUnitTranslations; + + public defaultPaddingEnable = true; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.geoFilterConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + latitudeKeyName: isDefinedAndNotNull(configuration?.latitudeKeyName) ? configuration.latitudeKeyName : null, + longitudeKeyName: isDefinedAndNotNull(configuration?.longitudeKeyName) ? configuration.longitudeKeyName : null, + perimeterType: isDefinedAndNotNull(configuration?.perimeterType) ? configuration.perimeterType : null, + fetchPerimeterInfoFromMessageMetadata: isDefinedAndNotNull(configuration?.fetchPerimeterInfoFromMessageMetadata) ? + configuration.fetchPerimeterInfoFromMessageMetadata : false, + perimeterKeyName: isDefinedAndNotNull(configuration?.perimeterKeyName) ? configuration.perimeterKeyName : null, + centerLatitude: isDefinedAndNotNull(configuration?.centerLatitude) ? configuration.centerLatitude : null, + centerLongitude: isDefinedAndNotNull(configuration?.centerLongitude) ? configuration.centerLongitude : null, + range: isDefinedAndNotNull(configuration?.range) ? configuration.range : null, + rangeUnit: isDefinedAndNotNull(configuration?.rangeUnit) ? configuration.rangeUnit : null, + polygonsDefinition: isDefinedAndNotNull(configuration?.polygonsDefinition) ? configuration.polygonsDefinition : null + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.geoFilterConfigForm = this.fb.group({ + latitudeKeyName: [configuration.latitudeKeyName, [Validators.required]], + longitudeKeyName: [configuration.longitudeKeyName, [Validators.required]], + perimeterType: [configuration.perimeterType, [Validators.required]], + fetchPerimeterInfoFromMessageMetadata: [configuration.fetchPerimeterInfoFromMessageMetadata, []], + perimeterKeyName: [configuration.perimeterKeyName, []], + centerLatitude: [configuration.centerLatitude, []], + centerLongitude: [configuration.centerLongitude, []], + range: [configuration.range, []], + rangeUnit: [configuration.rangeUnit, []], + polygonsDefinition: [configuration.polygonsDefinition, []] + }); + } + + protected validatorTriggers(): string[] { + return ['fetchPerimeterInfoFromMessageMetadata', 'perimeterType']; + } + + protected updateValidators(emitEvent: boolean) { + const fetchPerimeterInfoFromMessageMetadata: boolean = this.geoFilterConfigForm.get('fetchPerimeterInfoFromMessageMetadata').value; + const perimeterType: PerimeterType = this.geoFilterConfigForm.get('perimeterType').value; + if (fetchPerimeterInfoFromMessageMetadata) { + this.geoFilterConfigForm.get('perimeterKeyName').setValidators([Validators.required]); + } else { + this.geoFilterConfigForm.get('perimeterKeyName').setValidators([]); + } + if (!fetchPerimeterInfoFromMessageMetadata && perimeterType === PerimeterType.CIRCLE) { + this.geoFilterConfigForm.get('centerLatitude').setValidators([Validators.required, + Validators.min(-90), Validators.max(90)]); + this.geoFilterConfigForm.get('centerLongitude').setValidators([Validators.required, + Validators.min(-180), Validators.max(180)]); + this.geoFilterConfigForm.get('range').setValidators([Validators.required, Validators.min(0)]); + this.geoFilterConfigForm.get('rangeUnit').setValidators([Validators.required]); + + this.defaultPaddingEnable = false; + } else { + this.geoFilterConfigForm.get('centerLatitude').setValidators([]); + this.geoFilterConfigForm.get('centerLongitude').setValidators([]); + this.geoFilterConfigForm.get('range').setValidators([]); + this.geoFilterConfigForm.get('rangeUnit').setValidators([]); + + this.defaultPaddingEnable = true; + } + if (!fetchPerimeterInfoFromMessageMetadata && perimeterType === PerimeterType.POLYGON) { + this.geoFilterConfigForm.get('polygonsDefinition').setValidators([Validators.required]); + } else { + this.geoFilterConfigForm.get('polygonsDefinition').setValidators([]); + } + this.geoFilterConfigForm.get('perimeterKeyName').updateValueAndValidity({emitEvent}); + this.geoFilterConfigForm.get('centerLatitude').updateValueAndValidity({emitEvent}); + this.geoFilterConfigForm.get('centerLongitude').updateValueAndValidity({emitEvent}); + this.geoFilterConfigForm.get('range').updateValueAndValidity({emitEvent}); + this.geoFilterConfigForm.get('rangeUnit').updateValueAndValidity({emitEvent}); + this.geoFilterConfigForm.get('polygonsDefinition').updateValueAndValidity({emitEvent}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.html new file mode 100644 index 0000000000..1b347ca1d1 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.html @@ -0,0 +1,24 @@ + +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts new file mode 100644 index 0000000000..0f8392c4f0 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts @@ -0,0 +1,51 @@ +/// +/// 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 { AppState, isDefinedAndNotNull } from '@core/public-api'; +import { Store } from '@ngrx/store'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-filter-node-message-type-config', + templateUrl: './message-type-config.component.html', + styleUrls: [] +}) +export class MessageTypeConfigComponent extends RuleNodeConfigurationComponent { + + messageTypeConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.messageTypeConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + messageTypes: isDefinedAndNotNull(configuration?.messageTypes) ? configuration.messageTypes : null + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.messageTypeConfigForm = this.fb.group({ + messageTypes: [configuration.messageTypes, [Validators.required]] + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.html new file mode 100644 index 0000000000..233106bd8e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.html @@ -0,0 +1,31 @@ + +
    + + help + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.ts new file mode 100644 index 0000000000..91e945ee0f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.ts @@ -0,0 +1,65 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { EntityType } from '@app/shared/models/entity-type.models'; + +@Component({ + selector: 'tb-filter-node-originator-type-config', + templateUrl: './originator-type-config.component.html', + styleUrls: [] +}) +export class OriginatorTypeConfigComponent extends RuleNodeConfigurationComponent { + + originatorTypeConfigForm: UntypedFormGroup; + + allowedEntityTypes: EntityType[] = [ + EntityType.DEVICE, + EntityType.ASSET, + EntityType.ENTITY_VIEW, + EntityType.TENANT, + EntityType.CUSTOMER, + EntityType.USER, + EntityType.DASHBOARD, + EntityType.RULE_CHAIN, + EntityType.RULE_NODE, + EntityType.EDGE + ]; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.originatorTypeConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + originatorTypes: isDefinedAndNotNull(configuration?.originatorTypes) ? configuration.originatorTypes : null + }; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.originatorTypeConfigForm = this.fb.group({ + originatorTypes: [configuration.originatorTypes, [Validators.required]] + }); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/rule-node-config-filter.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/rule-node-config-filter.module.ts new file mode 100644 index 0000000000..52ad3169d5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/rule-node-config-filter.module.ts @@ -0,0 +1,69 @@ +/// +/// 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 { NgModule, Type } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { CheckMessageConfigComponent } from './check-message-config.component'; +import { CheckRelationConfigComponent } from './check-relation-config.component'; +import { GpsGeoFilterConfigComponent } from './gps-geo-filter-config.component'; +import { MessageTypeConfigComponent } from './message-type-config.component'; +import { OriginatorTypeConfigComponent } from './originator-type-config.component'; +import { ScriptConfigComponent } from './script-config.component'; +import { SwitchConfigComponent } from './switch-config.component'; +import { CheckAlarmStatusComponent } from './check-alarm-status.component'; +import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.module'; + +@NgModule({ + declarations: [ + CheckMessageConfigComponent, + CheckRelationConfigComponent, + GpsGeoFilterConfigComponent, + MessageTypeConfigComponent, + OriginatorTypeConfigComponent, + ScriptConfigComponent, + SwitchConfigComponent, + CheckAlarmStatusComponent + ], + imports: [ + CommonModule, + SharedModule, + RuleNodeConfigCommonModule + ], + exports: [ + CheckMessageConfigComponent, + CheckRelationConfigComponent, + GpsGeoFilterConfigComponent, + MessageTypeConfigComponent, + OriginatorTypeConfigComponent, + ScriptConfigComponent, + SwitchConfigComponent, + CheckAlarmStatusComponent + ] +}) +export class RuleNodeConfigFilterModule { +} + +export const ruleNodeFilterConfigComponentsMap: Record> = { + 'tbFilterNodeCheckAlarmStatusConfig': CheckAlarmStatusComponent, + 'tbFilterNodeCheckMessageConfig': CheckMessageConfigComponent, + 'tbFilterNodeCheckRelationConfig': CheckRelationConfigComponent, + 'tbFilterNodeGpsGeofencingConfig': GpsGeoFilterConfigComponent, + 'tbFilterNodeMessageTypeConfig': MessageTypeConfigComponent, + 'tbFilterNodeOriginatorTypeConfig': OriginatorTypeConfigComponent, + 'tbFilterNodeScriptConfig': ScriptConfigComponent, + 'tbFilterNodeSwitchConfig': SwitchConfigComponent +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.html new file mode 100644 index 0000000000..c0b39f77b7 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.html @@ -0,0 +1,57 @@ + +
    + + + + + + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts new file mode 100644 index 0000000000..643f66448f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/script-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, EventEmitter, ViewChild } from '@angular/core'; +import { AppState, getCurrentAuthState, isDefinedAndNotNull, NodeScriptTestService } from '@core/public-api'; +import { Store } from '@ngrx/store'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent, ScriptLanguage } from '@shared/models/rule-node.models'; +import type { JsFuncComponent } from '@app/shared/components/js-func.component'; +import { DebugRuleNodeEventBody } from '@app/shared/models/event.models'; + +@Component({ + selector: 'tb-filter-node-script-config', + templateUrl: './script-config.component.html', + styleUrls: [] +}) +export class ScriptConfigComponent extends RuleNodeConfigurationComponent { + + @ViewChild('jsFuncComponent', {static: false}) jsFuncComponent: JsFuncComponent; + @ViewChild('tbelFuncComponent', {static: false}) tbelFuncComponent: JsFuncComponent; + + scriptConfigForm: UntypedFormGroup; + + tbelEnabled = getCurrentAuthState(this.store).tbelEnabled; + + scriptLanguage = ScriptLanguage; + + changeScript: EventEmitter = new EventEmitter(); + + readonly hasScript = true; + + readonly testScriptLabel = 'tb.rulenode.test-filter-function'; + + constructor(protected store: Store, + private fb: UntypedFormBuilder, + private nodeScriptTestService: NodeScriptTestService, + private translate: TranslateService) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.scriptConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.scriptConfigForm = this.fb.group({ + scriptLang: [configuration.scriptLang, [Validators.required]], + jsScript: [configuration.jsScript, []], + tbelScript: [configuration.tbelScript, []] + }); + } + + protected validatorTriggers(): string[] { + return ['scriptLang']; + } + + protected updateValidators(emitEvent: boolean) { + let scriptLang: ScriptLanguage = this.scriptConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.TBEL && !this.tbelEnabled) { + scriptLang = ScriptLanguage.JS; + this.scriptConfigForm.get('scriptLang').patchValue(scriptLang, {emitEvent: false}); + setTimeout(() => { + this.scriptConfigForm.updateValueAndValidity({emitEvent: true}); + }); + } + this.scriptConfigForm.get('jsScript').setValidators(scriptLang === ScriptLanguage.JS ? [Validators.required] : []); + this.scriptConfigForm.get('jsScript').updateValueAndValidity({emitEvent}); + this.scriptConfigForm.get('tbelScript').setValidators(scriptLang === ScriptLanguage.TBEL ? [Validators.required] : []); + this.scriptConfigForm.get('tbelScript').updateValueAndValidity({emitEvent}); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (configuration) { + if (!configuration.scriptLang) { + configuration.scriptLang = ScriptLanguage.JS; + } + } + return { + scriptLang: isDefinedAndNotNull(configuration?.scriptLang) ? configuration.scriptLang : ScriptLanguage.JS, + jsScript: isDefinedAndNotNull(configuration?.jsScript) ? configuration.jsScript : null, + tbelScript: isDefinedAndNotNull(configuration?.tbelScript) ? configuration.tbelScript : null + }; + } + + testScript(debugEventBody?: DebugRuleNodeEventBody) { + const scriptLang: ScriptLanguage = this.scriptConfigForm.get('scriptLang').value; + const scriptField = scriptLang === ScriptLanguage.JS ? 'jsScript' : 'tbelScript'; + const helpId = scriptLang === ScriptLanguage.JS ? 'rulenode/filter_node_script_fn' : 'rulenode/tbel/filter_node_script_fn'; + const script: string = this.scriptConfigForm.get(scriptField).value; + this.nodeScriptTestService.testNodeScript( + script, + 'filter', + this.translate.instant('tb.rulenode.filter'), + 'Filter', + ['msg', 'metadata', 'msgType'], + this.ruleNodeId, + helpId, + scriptLang, + debugEventBody + ).subscribe((theScript) => { + if (theScript) { + this.scriptConfigForm.get(scriptField).setValue(theScript); + this.changeScript.emit(); + } + }); + } + + protected onValidate() { + const scriptLang: ScriptLanguage = this.scriptConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.JS) { + this.jsFuncComponent.validateOnSubmit(); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.html new file mode 100644 index 0000000000..83034e2e43 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.html @@ -0,0 +1,57 @@ + +
    + + + + + + + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts new file mode 100644 index 0000000000..a77e5d3e29 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts @@ -0,0 +1,130 @@ +/// +/// 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, EventEmitter, ViewChild } from '@angular/core'; +import { getCurrentAuthState, isDefinedAndNotNull, NodeScriptTestService } from '@core/public-api'; +import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { + RuleNodeConfiguration, + RuleNodeConfigurationComponent, + ScriptLanguage +} from '@app/shared/models/rule-node.models'; +import type { JsFuncComponent } from '@app/shared/components/js-func.component'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; + +@Component({ + selector: 'tb-filter-node-switch-config', + templateUrl: './switch-config.component.html', + styleUrls: [] +}) +export class SwitchConfigComponent extends RuleNodeConfigurationComponent { + + @ViewChild('jsFuncComponent', {static: false}) jsFuncComponent: JsFuncComponent; + @ViewChild('tbelFuncComponent', {static: false}) tbelFuncComponent: JsFuncComponent; + + switchConfigForm: UntypedFormGroup; + + tbelEnabled = getCurrentAuthState(this.store).tbelEnabled; + + scriptLanguage = ScriptLanguage; + + changeScript: EventEmitter = new EventEmitter(); + + readonly hasScript = true; + + readonly testScriptLabel = 'tb.rulenode.test-switch-function'; + + constructor(private fb: UntypedFormBuilder, + private nodeScriptTestService: NodeScriptTestService, + private translate: TranslateService) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.switchConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.switchConfigForm = this.fb.group({ + scriptLang: [configuration.scriptLang, [Validators.required]], + jsScript: [configuration.jsScript, []], + tbelScript: [configuration.tbelScript, []] + }); + } + + protected validatorTriggers(): string[] { + return ['scriptLang']; + } + + protected updateValidators(emitEvent: boolean) { + let scriptLang: ScriptLanguage = this.switchConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.TBEL && !this.tbelEnabled) { + scriptLang = ScriptLanguage.JS; + this.switchConfigForm.get('scriptLang').patchValue(scriptLang, {emitEvent: false}); + setTimeout(() => { + this.switchConfigForm.updateValueAndValidity({emitEvent: true}); + }); + } + this.switchConfigForm.get('jsScript').setValidators(scriptLang === ScriptLanguage.JS ? [Validators.required] : []); + this.switchConfigForm.get('jsScript').updateValueAndValidity({emitEvent}); + this.switchConfigForm.get('tbelScript').setValidators(scriptLang === ScriptLanguage.TBEL ? [Validators.required] : []); + this.switchConfigForm.get('tbelScript').updateValueAndValidity({emitEvent}); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (configuration) { + if (!configuration.scriptLang) { + configuration.scriptLang = ScriptLanguage.JS; + } + } + return { + scriptLang: isDefinedAndNotNull(configuration?.scriptLang) ? configuration.scriptLang : ScriptLanguage.JS, + jsScript: isDefinedAndNotNull(configuration?.jsScript) ? configuration.jsScript : null, + tbelScript: isDefinedAndNotNull(configuration?.tbelScript) ? configuration.tbelScript : null + }; + } + + testScript(debugEventBody?: DebugRuleNodeEventBody) { + const scriptLang: ScriptLanguage = this.switchConfigForm.get('scriptLang').value; + const scriptField = scriptLang === ScriptLanguage.JS ? 'jsScript' : 'tbelScript'; + const helpId = scriptLang === ScriptLanguage.JS ? 'rulenode/switch_node_script_fn' : 'rulenode/tbel/switch_node_script_fn'; + const script: string = this.switchConfigForm.get(scriptField).value; + this.nodeScriptTestService.testNodeScript( + script, + 'switch', + this.translate.instant('tb.rulenode.switch'), + 'Switch', + ['msg', 'metadata', 'msgType'], + this.ruleNodeId, + helpId, + scriptLang, + debugEventBody + ).subscribe((theScript) => { + if (theScript) { + this.switchConfigForm.get(scriptField).setValue(theScript); + this.changeScript.emit(); + } + }); + } + + protected onValidate() { + const scriptLang: ScriptLanguage = this.switchConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.JS) { + this.jsFuncComponent.validateOnSubmit(); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.html b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.html new file mode 100644 index 0000000000..a91b9980d4 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.html @@ -0,0 +1,33 @@ + +
    +
    +
    + + {{ 'tb.rulenode.forward-msg-default-rule-chain' | translate }} + +
    + + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.ts new file mode 100644 index 0000000000..9e5316841a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.ts @@ -0,0 +1,48 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { EntityType } from '@shared/models/entity-type.models'; + +@Component({ + selector: 'tb-flow-node-rule-chain-input-config', + templateUrl: './rule-chain-input.component.html', + styleUrls: [] +}) +export class RuleChainInputComponent extends RuleNodeConfigurationComponent { + + entityType = EntityType; + + ruleChainInputConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.ruleChainInputConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.ruleChainInputConfigForm = this.fb.group({ + forwardMsgToDefaultRuleChain: [configuration ? configuration?.forwardMsgToDefaultRuleChain : false, []], + ruleChainId: [configuration ? configuration.ruleChainId : null, [Validators.required]] + }); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.html b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.html new file mode 100644 index 0000000000..d5c039c030 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.html @@ -0,0 +1,20 @@ + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.ts new file mode 100644 index 0000000000..153272f374 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-output.component.ts @@ -0,0 +1,42 @@ +/// +/// 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 { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-flow-node-rule-chain-output-config', + templateUrl: './rule-chain-output.component.html', + styleUrls: [] +}) +export class RuleChainOutputComponent extends RuleNodeConfigurationComponent { + + ruleChainOutputConfigForm: UntypedFormGroup; + + constructor(private fb: UntypedFormBuilder) { + super(); + } + + protected configForm(): UntypedFormGroup { + return this.ruleChainOutputConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.ruleChainOutputConfigForm = this.fb.group({}); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-node-config-flow.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-node-config-flow.module.ts new file mode 100644 index 0000000000..4dae3212aa --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-node-config-flow.module.ts @@ -0,0 +1,43 @@ +/// +/// 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 { NgModule, Type } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { RuleChainInputComponent } from './rule-chain-input.component'; +import { RuleChainOutputComponent } from './rule-chain-output.component'; + +@NgModule({ + declarations: [ + RuleChainInputComponent, + RuleChainOutputComponent + ], + imports: [ + CommonModule, + SharedModule + ], + exports: [ + RuleChainInputComponent, + RuleChainOutputComponent + ] +}) +export class RuleNodeConfigFlowModule { +} + +export const ruleNodeFlowConfigComponentsMap: Record> = { + 'tbFlowNodeRuleChainInputConfig': RuleChainInputComponent, + 'tbFlowNodeRuleChainOutputConfig': RuleChainOutputComponent +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.models.ts b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.models.ts new file mode 100644 index 0000000000..6562a732aa --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.models.ts @@ -0,0 +1,862 @@ +/// +/// 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 { EntityField, entityFields } from '@shared/models/entity.models'; +import { EntitySearchDirection } from '@shared/models/relation.models'; +import { EntityTypeFilter } from '@shared/models/alias.models'; + +export enum OriginatorSource { + CUSTOMER = 'CUSTOMER', + TENANT = 'TENANT', + RELATED = 'RELATED', + ALARM_ORIGINATOR = 'ALARM_ORIGINATOR', + ENTITY = 'ENTITY' +} + +export interface OriginatorValuesDescriptions { + value: OriginatorSource; + name: string; + description: string; +} + +export const originatorSourceTranslations = new Map( + [ + [OriginatorSource.CUSTOMER, 'tb.rulenode.originator-customer'], + [OriginatorSource.TENANT, 'tb.rulenode.originator-tenant'], + [OriginatorSource.RELATED, 'tb.rulenode.originator-related'], + [OriginatorSource.ALARM_ORIGINATOR, 'tb.rulenode.originator-alarm-originator'], + [OriginatorSource.ENTITY, 'tb.rulenode.originator-entity'], + ] +); + +export const originatorSourceDescTranslations = new Map( + [ + [OriginatorSource.CUSTOMER, 'tb.rulenode.originator-customer-desc'], + [OriginatorSource.TENANT, 'tb.rulenode.originator-tenant-desc'], + [OriginatorSource.RELATED, 'tb.rulenode.originator-related-entity-desc'], + [OriginatorSource.ALARM_ORIGINATOR, 'tb.rulenode.originator-alarm-originator-desc'], + [OriginatorSource.ENTITY, 'tb.rulenode.originator-entity-by-name-pattern-desc'], + ] +); +export const allowedOriginatorFields: EntityField[] = [ + entityFields.createdTime, + entityFields.name, + {value: 'type', name: 'tb.rulenode.profile-name', keyName: 'originatorProfileName'}, + entityFields.firstName, + entityFields.lastName, + entityFields.email, + entityFields.title, + entityFields.country, + entityFields.state, + entityFields.city, + entityFields.address, + entityFields.address2, + entityFields.zip, + entityFields.phone, + entityFields.label, + {value: 'id', name: 'tb.rulenode.id', keyName: 'id'}, + {value: 'additionalInfo', name: 'tb.rulenode.additional-info', keyName: 'additionalInfo'} +]; + +export const OriginatorFieldsMappingValues = 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'], + ] +); + +export enum PerimeterType { + CIRCLE = 'CIRCLE', + POLYGON = 'POLYGON' +} + +export const perimeterTypeTranslations = new Map( + [ + [PerimeterType.CIRCLE, 'tb.rulenode.perimeter-circle'], + [PerimeterType.POLYGON, 'tb.rulenode.perimeter-polygon'], + ] +); + +export enum TimeUnit { + MILLISECONDS = 'MILLISECONDS', + SECONDS = 'SECONDS', + MINUTES = 'MINUTES', + HOURS = 'HOURS', + DAYS = 'DAYS' +} + +export const timeUnitTranslations = new Map( + [ + [TimeUnit.MILLISECONDS, 'tb.rulenode.time-unit-milliseconds'], + [TimeUnit.SECONDS, 'tb.rulenode.time-unit-seconds'], + [TimeUnit.MINUTES, 'tb.rulenode.time-unit-minutes'], + [TimeUnit.HOURS, 'tb.rulenode.time-unit-hours'], + [TimeUnit.DAYS, 'tb.rulenode.time-unit-days'] + ] +); + +export enum RangeUnit { + METER = 'METER', + KILOMETER = 'KILOMETER', + FOOT = 'FOOT', + MILE = 'MILE', + NAUTICAL_MILE = 'NAUTICAL_MILE' +} + +export const rangeUnitTranslations = new Map( + [ + [RangeUnit.METER, 'tb.rulenode.range-unit-meter'], + [RangeUnit.KILOMETER, 'tb.rulenode.range-unit-kilometer'], + [RangeUnit.FOOT, 'tb.rulenode.range-unit-foot'], + [RangeUnit.MILE, 'tb.rulenode.range-unit-mile'], + [RangeUnit.NAUTICAL_MILE, 'tb.rulenode.range-unit-nautical-mile'] + ] +); + +export enum EntityDetailsField { + ID = 'ID', + TITLE = 'TITLE', + COUNTRY = 'COUNTRY', + STATE = 'STATE', + CITY = 'CITY', + ZIP = 'ZIP', + ADDRESS = 'ADDRESS', + ADDRESS2 = 'ADDRESS2', + PHONE = 'PHONE', + EMAIL = 'EMAIL', + ADDITIONAL_INFO = 'ADDITIONAL_INFO' +} + +export interface SvMapOption { + name: string; + value: any; +} + +export const entityDetailsTranslations = new Map( + [ + [EntityDetailsField.ID, 'tb.rulenode.entity-details-id'], + [EntityDetailsField.TITLE, 'tb.rulenode.entity-details-title'], + [EntityDetailsField.COUNTRY, 'tb.rulenode.entity-details-country'], + [EntityDetailsField.STATE, 'tb.rulenode.entity-details-state'], + [EntityDetailsField.CITY, 'tb.rulenode.entity-details-city'], + [EntityDetailsField.ZIP, 'tb.rulenode.entity-details-zip'], + [EntityDetailsField.ADDRESS, 'tb.rulenode.entity-details-address'], + [EntityDetailsField.ADDRESS2, 'tb.rulenode.entity-details-address2'], + [EntityDetailsField.PHONE, 'tb.rulenode.entity-details-phone'], + [EntityDetailsField.EMAIL, 'tb.rulenode.entity-details-email'], + [EntityDetailsField.ADDITIONAL_INFO, 'tb.rulenode.entity-details-additional_info'] + ] +); + +export enum FetchMode { + FIRST = 'FIRST', + LAST = 'LAST', + ALL = 'ALL' +} + +export const deduplicationStrategiesTranslations = new Map( + [ + [FetchMode.FIRST, 'tb.rulenode.first'], + [FetchMode.LAST, 'tb.rulenode.last'], + [FetchMode.ALL, 'tb.rulenode.all'] + ] +); + +export const deduplicationStrategiesHintTranslations = new Map( + [ + [FetchMode.FIRST, 'tb.rulenode.first-mode-hint'], + [FetchMode.LAST, 'tb.rulenode.last-mode-hint'], + [FetchMode.ALL, 'tb.rulenode.all-mode-hint'] + ] +); + +export enum SamplingOrder { + ASC = 'ASC', + DESC = 'DESC' +} + +export enum DataToFetch { + ATTRIBUTES = 'ATTRIBUTES', + LATEST_TELEMETRY = 'LATEST_TELEMETRY', + FIELDS = 'FIELDS' +} + +export const dataToFetchTranslations = new Map( + [ + [DataToFetch.ATTRIBUTES, 'tb.rulenode.attributes'], + [DataToFetch.LATEST_TELEMETRY, 'tb.rulenode.latest-telemetry'], + [DataToFetch.FIELDS, 'tb.rulenode.fields'] + ] +); + +export const msgMetadataLabelTranslations = new Map( + [ + [DataToFetch.ATTRIBUTES, 'tb.rulenode.add-mapped-attribute-to'], + [DataToFetch.LATEST_TELEMETRY, 'tb.rulenode.add-mapped-latest-telemetry-to'], + [DataToFetch.FIELDS, 'tb.rulenode.add-mapped-fields-to'] + ] +); + +export const samplingOrderTranslations = new Map( + [ + [SamplingOrder.ASC, 'tb.rulenode.ascending'], + [SamplingOrder.DESC, 'tb.rulenode.descending'] + ] +); + +export enum SqsQueueType { + STANDARD = 'STANDARD', + FIFO = 'FIFO' +} + +export const sqsQueueTypeTranslations = new Map( + [ + [SqsQueueType.STANDARD, 'tb.rulenode.sqs-queue-standard'], + [SqsQueueType.FIFO, 'tb.rulenode.sqs-queue-fifo'], + ] +); + +export type credentialsType = 'anonymous' | 'basic' | 'cert.PEM'; +export const credentialsTypes: credentialsType[] = ['anonymous', 'basic', 'cert.PEM']; + +export const credentialsTypeTranslations = new Map( + [ + ['anonymous', 'tb.rulenode.credentials-anonymous'], + ['basic', 'tb.rulenode.credentials-basic'], + ['cert.PEM', 'tb.rulenode.credentials-pem'] + ] +); + +export type AzureIotHubCredentialsType = 'sas' | 'cert.PEM'; +export const azureIotHubCredentialsTypes: AzureIotHubCredentialsType[] = ['sas', 'cert.PEM']; + +export const azureIotHubCredentialsTypeTranslations = new Map( + [ + ['sas', 'tb.rulenode.credentials-sas'], + ['cert.PEM', 'tb.rulenode.credentials-pem'] + ] +); + +export enum HttpRequestType { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE' +} + +export const ToByteStandartCharsetTypes = [ + 'US-ASCII', + 'ISO-8859-1', + 'UTF-8', + 'UTF-16BE', + 'UTF-16LE', + 'UTF-16' +]; + +export const ToByteStandartCharsetTypeTranslations = 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'], + ] +); + +export interface RelationsQuery { + fetchLastLevelOnly: boolean; + direction: EntitySearchDirection; + maxLevel?: number; + filters?: EntityTypeFilter[]; +} + +export interface FunctionData { + value: MathFunction; + name: string; + description: string; + minArgs: number; + maxArgs: number; +} + +export enum MathFunction { + CUSTOM = 'CUSTOM', + ADD = 'ADD', + SUB = 'SUB', + MULT = 'MULT', + DIV = 'DIV', + SIN = 'SIN', + SINH = 'SINH', + COS = 'COS', + COSH = 'COSH', + TAN = 'TAN', + TANH = 'TANH', + ACOS = 'ACOS', + ASIN = 'ASIN', + ATAN = 'ATAN', + ATAN2 = 'ATAN2', + EXP = 'EXP', + EXPM1 = 'EXPM1', + SQRT = 'SQRT', + CBRT = 'CBRT', + GET_EXP = 'GET_EXP', + HYPOT = 'HYPOT', + LOG = 'LOG', + LOG10 = 'LOG10', + LOG1P = 'LOG1P', + CEIL = 'CEIL', + FLOOR = 'FLOOR', + FLOOR_DIV = 'FLOOR_DIV', + FLOOR_MOD = 'FLOOR_MOD', + ABS = 'ABS', + MIN = 'MIN', + MAX = 'MAX', + POW = 'POW', + SIGNUM = 'SIGNUM', + RAD = 'RAD', + DEG = 'DEG', +} + +export const MathFunctionMap = new Map( + [ + [ + MathFunction.CUSTOM, + { + value: MathFunction.CUSTOM, + name: 'Custom Function', + description: 'Use this function to specify complex mathematical expression.', + minArgs: 1, + maxArgs: 16 + } + ], + [ + MathFunction.ADD, + { + value: MathFunction.ADD, + name: 'Addition', + description: 'x + y', + minArgs: 2, + maxArgs: 2 + } + ], + [ + MathFunction.SUB, + { + value: MathFunction.SUB, + name: 'Subtraction', + description: 'x - y', + minArgs: 2, + maxArgs: 2 + } + ], + [ + MathFunction.MULT, + { + value: MathFunction.MULT, + name: 'Multiplication', + description: 'x * y', + minArgs: 2, + maxArgs: 2 + } + ], + [ + MathFunction.DIV, + { + value: MathFunction.DIV, + name: 'Division', + description: 'x / y', + minArgs: 2, + maxArgs: 2 + } + ], + [ + MathFunction.SIN, + { + value: MathFunction.SIN, + name: 'Sine', + description: 'Returns the trigonometric sine of an angle in radians.', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.SINH, + { + value: MathFunction.SINH, + name: 'Hyperbolic sine', + description: 'Returns the hyperbolic sine of an argument.', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.COS, + { + value: MathFunction.COS, + name: 'Cosine', + description: 'Returns the trigonometric cosine of an angle in radians.', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.COSH, + { + value: MathFunction.COSH, + name: 'Hyperbolic cosine', + description: 'Returns the hyperbolic cosine of an argument.', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.TAN, + { + value: MathFunction.TAN, + name: 'Tangent', + description: 'Returns the trigonometric tangent of an angle in radians', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.TANH, + { + value: MathFunction.TANH, + name: 'Hyperbolic tangent', + description: 'Returns the hyperbolic tangent of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.ACOS, + { + value: MathFunction.ACOS, + name: 'Arc cosine', + description: 'Returns the arc cosine of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.ASIN, + { + value: MathFunction.ASIN, + name: 'Arc sine', + description: 'Returns the arc sine of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.ATAN, + { + value: MathFunction.ATAN, + name: 'Arc tangent', + description: 'Returns the arc tangent of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.ATAN2, + { + value: MathFunction.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 + } + ], + [ + MathFunction.EXP, + { + value: MathFunction.EXP, + name: 'Exponential', + description: 'Returns Euler\'s number e raised to the power of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.EXPM1, + { + value: MathFunction.EXPM1, + name: 'Exponential minus one', + description: 'Returns Euler\'s number e raised to the power of an argument minus one', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.SQRT, + { + value: MathFunction.SQRT, + name: 'Square', + description: 'Returns the correctly rounded positive square root of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.CBRT, + { + value: MathFunction.CBRT, + name: 'Cube root', + description: 'Returns the cube root of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.GET_EXP, + { + value: MathFunction.GET_EXP, + name: 'Get exponent', + description: 'Returns the unbiased exponent used in the representation of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.HYPOT, + { + value: MathFunction.HYPOT, + name: 'Square root', + description: 'Returns the square root of the squares of the arguments', + minArgs: 2, + maxArgs: 2 + } + ], + [ + MathFunction.LOG, + { + value: MathFunction.LOG, + name: 'Logarithm', + description: 'Returns the natural logarithm of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.LOG10, + { + value: MathFunction.LOG10, + name: 'Base 10 logarithm', + description: 'Returns the base 10 logarithm of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.LOG1P, + { + value: MathFunction.LOG1P, + name: 'Logarithm of the sum', + description: 'Returns the natural logarithm of the sum of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.CEIL, + { + value: MathFunction.CEIL, + name: 'Ceiling', + description: 'Returns the smallest (closest to negative infinity) of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.FLOOR, + { + value: MathFunction.FLOOR, + name: 'Floor', + description: 'Returns the largest (closest to positive infinity) of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.FLOOR_DIV, + { + value: MathFunction.FLOOR_DIV, + name: 'Floor division', + description: 'Returns the largest (closest to positive infinity) of the arguments', + minArgs: 2, + maxArgs: 2 + } + ], + [ + MathFunction.FLOOR_MOD, + { + value: MathFunction.FLOOR_MOD, + name: 'Floor modulus', + description: 'Returns the floor modulus of the arguments', + minArgs: 2, + maxArgs: 2 + } + ], + [ + MathFunction.ABS, + { + value: MathFunction.ABS, + name: 'Absolute', + description: 'Returns the absolute value of an argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.MIN, + { + value: MathFunction.MIN, + name: 'Min', + description: 'Returns the smaller of the arguments', + minArgs: 2, + maxArgs: 2 + } + ], + [ + MathFunction.MAX, + { + value: MathFunction.MAX, + name: 'Max', + description: 'Returns the greater of the arguments', + minArgs: 2, + maxArgs: 2 + } + ], + [ + MathFunction.POW, + { + value: MathFunction.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 + } + ], + [ + MathFunction.SIGNUM, + { + value: MathFunction.SIGNUM, + name: 'Sign of a real number', + description: 'Returns the signum function of the argument', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.RAD, + { + value: MathFunction.RAD, + name: 'Radian', + description: 'Converts an angle measured in degrees to an approximately equivalent angle measured in radians', + minArgs: 1, + maxArgs: 1 + } + ], + [ + MathFunction.DEG, + { + value: MathFunction.DEG, + name: 'Degrees', + description: 'Converts an angle measured in radians to an approximately equivalent angle measured in degrees.', + minArgs: 1, + maxArgs: 1 + } + ], + ]); + +export enum ArgumentType { + MESSAGE_BODY = 'MESSAGE_BODY', + MESSAGE_METADATA = 'MESSAGE_METADATA', + ATTRIBUTE = 'ATTRIBUTE', + TIME_SERIES = 'TIME_SERIES', + CONSTANT = 'CONSTANT' +} + +export enum ArgumentTypeResult { + MESSAGE_BODY = 'MESSAGE_BODY', + MESSAGE_METADATA = 'MESSAGE_METADATA', + ATTRIBUTE = 'ATTRIBUTE', + TIME_SERIES = 'TIME_SERIES' +} + +export enum FetchTo { + DATA = 'DATA', + METADATA = 'METADATA' +} + +export const FetchFromToTranslation = new Map([ + [FetchTo.DATA, 'tb.rulenode.message-to-metadata'], + [FetchTo.METADATA, 'tb.rulenode.metadata-to-message'], +]); + +export const FetchFromTranslation = new Map([ + [FetchTo.DATA, 'tb.rulenode.from-message'], + [FetchTo.METADATA, 'tb.rulenode.from-metadata'], +]); + +export const FetchToTranslation = new Map([ + [FetchTo.DATA, 'tb.rulenode.message'], + [FetchTo.METADATA, 'tb.rulenode.metadata'], +]); + +export const FetchToRenameTranslation = new Map([ + [FetchTo.DATA, 'tb.rulenode.message'], + [FetchTo.METADATA, 'tb.rulenode.message-metadata'], +]); + +export interface ArgumentTypeData { + name: string; + description: string; +} + +export const ArgumentTypeMap = new Map([ + [ + ArgumentType.MESSAGE_BODY, + { + name: 'tb.rulenode.message-body-type', + description: 'Fetch argument value from incoming message' + } + ], + [ + ArgumentType.MESSAGE_METADATA, + { + name: 'tb.rulenode.message-metadata-type', + description: 'Fetch argument value from incoming message metadata' + } + ], + [ + ArgumentType.ATTRIBUTE, + { + name: 'tb.rulenode.attribute-type', + description: 'Fetch attribute value from database' + } + ], + [ + ArgumentType.TIME_SERIES, + { + name: 'tb.rulenode.time-series-type', + description: 'Fetch latest time-series value from database' + } + ], + [ + ArgumentType.CONSTANT, + { + name: 'tb.rulenode.constant-type', + description: 'Define constant value' + } + ] +]); + +export const ArgumentTypeResultMap = new Map([ + [ + ArgumentTypeResult.MESSAGE_BODY, + { + name: 'tb.rulenode.message-body-type', + description: 'Add result to the outgoing message' + } + ], + [ + ArgumentTypeResult.MESSAGE_METADATA, + { + name: 'tb.rulenode.message-metadata-type', + description: 'Add result to the outgoing message metadata' + } + ], + [ + ArgumentTypeResult.ATTRIBUTE, + { + name: 'tb.rulenode.attribute-type', + description: 'Store result as an entity attribute in the database' + } + ], + [ + ArgumentTypeResult.TIME_SERIES, + { + name: 'tb.rulenode.time-series-type', + description: 'Store result as an entity time-series in the database' + } + ] +]); + +export const ArgumentName = ['x', 'y', 'z', 'a', 'b', 'c', 'd', 'k', 'l', 'm', 'n', 'o', 'p', 'r', 's', 't']; + +export enum AttributeScope { + SHARED_SCOPE = 'SHARED_SCOPE', + SERVER_SCOPE = 'SERVER_SCOPE', + CLIENT_SCOPE = 'CLIENT_SCOPE' +} + +export enum AttributeScopeResult { + SHARED_SCOPE = 'SHARED_SCOPE', + SERVER_SCOPE = 'SERVER_SCOPE' +} + +export const AttributeScopeMap = new Map([ + [AttributeScope.SHARED_SCOPE, 'tb.rulenode.shared-scope'], + [AttributeScope.SERVER_SCOPE, 'tb.rulenode.server-scope'], + [AttributeScope.CLIENT_SCOPE, 'tb.rulenode.client-scope'] +]); + +export enum PresenceMonitoringStrategy { + ON_FIRST_MESSAGE = 'ON_FIRST_MESSAGE', + ON_EACH_MESSAGE = 'ON_EACH_MESSAGE' +} + +export interface PresenceMonitoringStrategyData { + value: boolean; + name: string; +} + +export const PresenceMonitoringStrategiesData = new Map([ + [ + PresenceMonitoringStrategy.ON_EACH_MESSAGE, + { + value: true, + name: 'tb.rulenode.presence-monitoring-strategy-on-each-message' + } + ], + [ + PresenceMonitoringStrategy.ON_FIRST_MESSAGE, + { + value: false, + name: 'tb.rulenode.presence-monitoring-strategy-on-first-message' + } + ] +]); + +export const IntLimit = 2147483648; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts new file mode 100644 index 0000000000..79d46f02d5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts @@ -0,0 +1,75 @@ +/// +/// 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 { NgModule, Type } from '@angular/core'; +import { EmptyConfigComponent } from './empty-config.component'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { + ruleNodeActionConfigComponentsMap, + RuleNodeConfigActionModule +} from '@home/components/rule-node/action/rule-node-config-action.module'; +import { + RuleNodeConfigFilterModule, + ruleNodeFilterConfigComponentsMap +} from '@home/components/rule-node/filter/rule-node-config-filter.module'; +import { + RuleNodeCoreEnrichmentModule, + ruleNodeEnrichmentConfigComponentsMap +} from '@home/components/rule-node/enrichment/rule-node-core-enrichment.module'; +import { + RuleNodeConfigExternalModule, + ruleNodeExternalConfigComponentsMap +} from '@home/components/rule-node/external/rule-node-config-external.module'; +import { + RuleNodeConfigTransformModule, + ruleNodeTransformConfigComponentsMap +} from '@home/components/rule-node/transform/rule-node-config-transform.module'; +import { + RuleNodeConfigFlowModule, + ruleNodeFlowConfigComponentsMap +} from '@home/components/rule-node/flow/rule-node-config-flow.module'; +import { IRuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@NgModule({ + declarations: [ + EmptyConfigComponent + ], + imports: [ + CommonModule, + SharedModule + ], + exports: [ + RuleNodeConfigActionModule, + RuleNodeConfigFilterModule, + RuleNodeCoreEnrichmentModule, + RuleNodeConfigExternalModule, + RuleNodeConfigTransformModule, + RuleNodeConfigFlowModule, + EmptyConfigComponent + ] +}) +export class RuleNodeConfigModule {} + +export const ruleNodeConfigComponentsMap: Record> = { + ...ruleNodeActionConfigComponentsMap, + ...ruleNodeEnrichmentConfigComponentsMap, + ...ruleNodeExternalConfigComponentsMap, + ...ruleNodeFilterConfigComponentsMap, + ...ruleNodeFlowConfigComponentsMap, + ...ruleNodeTransformConfigComponentsMap, + 'tbNodeEmptyConfig': EmptyConfigComponent +}; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.html new file mode 100644 index 0000000000..818ea5a12d --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.html @@ -0,0 +1,66 @@ + +
    + + tb.rulenode.new-originator + + + + {{ originatorSourceTranslationMap.get(changeOriginatorConfigForm.get('originatorSource').value) | translate }} + + + + + {{ originatorSourceTranslationMap.get(source) | translate }} + +
    + + {{ originatorSourceDescTranslationMap.get(source) | translate }} + +
    +
    +
    +
    + + +
    + + + + tb.rulenode.entity-name-pattern + + + {{ 'tb.rulenode.entity-name-pattern-required' | translate }} + + +
    +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.ts new file mode 100644 index 0000000000..954dd412e5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.ts @@ -0,0 +1,83 @@ +/// +/// 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 { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { + OriginatorSource, + originatorSourceDescTranslations, + originatorSourceTranslations +} from '@home/components/rule-node/rule-node-config.models'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { EntityType } from '@app/shared/models/entity-type.models'; + +@Component({ + selector: 'tb-transformation-node-change-originator-config', + templateUrl: './change-originator-config.component.html' +}) +export class ChangeOriginatorConfigComponent extends RuleNodeConfigurationComponent { + + originatorSource = OriginatorSource; + originatorSources = Object.keys(OriginatorSource) as OriginatorSource[]; + originatorSourceTranslationMap = originatorSourceTranslations; + originatorSourceDescTranslationMap = originatorSourceDescTranslations; + + changeOriginatorConfigForm: FormGroup; + + allowedEntityTypes = [EntityType.DEVICE, EntityType.ASSET, EntityType.ENTITY_VIEW, EntityType.USER, EntityType.EDGE]; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.changeOriginatorConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.changeOriginatorConfigForm = this.fb.group({ + originatorSource: [configuration ? configuration.originatorSource : null, [Validators.required]], + entityType: [configuration ? configuration.entityType : null, []], + entityNamePattern: [configuration ? configuration.entityNamePattern : null, []], + relationsQuery: [configuration ? configuration.relationsQuery : null, []] + }); + } + + protected validatorTriggers(): string[] { + return ['originatorSource']; + } + + protected updateValidators(emitEvent: boolean) { + const originatorSource: OriginatorSource = this.changeOriginatorConfigForm.get('originatorSource').value; + if (originatorSource === OriginatorSource.RELATED) { + this.changeOriginatorConfigForm.get('relationsQuery').setValidators([Validators.required]); + } else { + this.changeOriginatorConfigForm.get('relationsQuery').setValidators([]); + } + if (originatorSource === OriginatorSource.ENTITY) { + this.changeOriginatorConfigForm.get('entityType').setValidators([Validators.required]); + this.changeOriginatorConfigForm.get('entityNamePattern').setValidators([Validators.required, Validators.pattern(/.*\S.*/)]); + } else { + this.changeOriginatorConfigForm.get('entityType').patchValue(null, {emitEvent}); + this.changeOriginatorConfigForm.get('entityNamePattern').patchValue(null, {emitEvent}); + this.changeOriginatorConfigForm.get('entityType').setValidators([]); + this.changeOriginatorConfigForm.get('entityNamePattern').setValidators([]); + } + this.changeOriginatorConfigForm.get('relationsQuery').updateValueAndValidity({emitEvent}); + this.changeOriginatorConfigForm.get('entityType').updateValueAndValidity({emitEvent}); + this.changeOriginatorConfigForm.get('entityNamePattern').updateValueAndValidity({emitEvent}); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.html new file mode 100644 index 0000000000..85cf878a4b --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.html @@ -0,0 +1,36 @@ + +
    + + + + + help + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.ts new file mode 100644 index 0000000000..1fcf4a7053 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.ts @@ -0,0 +1,73 @@ +/// +/// 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 { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { isDefinedAndNotNull } from '@core/public-api'; +import { TranslateService } from '@ngx-translate/core'; +import { FetchFromToTranslation, FetchTo } from '../rule-node-config.models'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; + +@Component({ + selector: 'tb-transformation-node-copy-keys-config', + templateUrl: './copy-keys-config.component.html', + styleUrls: [] +}) + +export class CopyKeysConfigComponent extends RuleNodeConfigurationComponent{ + copyKeysConfigForm: FormGroup; + copyFrom = []; + translation = FetchFromToTranslation; + + constructor(private fb: FormBuilder, + private translate: TranslateService) { + super(); + for (const key of this.translation.keys()) { + this.copyFrom.push({ + value: key, + name: this.translate.instant(this.translation.get(key)) + }); + } + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.copyKeysConfigForm = this.fb.group({ + copyFrom: [configuration.copyFrom , [Validators.required]], + keys: [configuration ? configuration.keys : null, [Validators.required]] + }); + } + + protected configForm(): FormGroup { + return this.copyKeysConfigForm; + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + let copyFrom: FetchTo; + + if (isDefinedAndNotNull(configuration?.fromMetadata)) { + copyFrom = configuration.copyFrom ? FetchTo.METADATA : FetchTo.DATA; + } else if (isDefinedAndNotNull(configuration?.copyFrom)) { + copyFrom = configuration.copyFrom; + } else { + copyFrom = FetchTo.DATA; + } + + return { + keys: isDefinedAndNotNull(configuration?.keys) ? configuration.keys : null, + copyFrom + }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.html new file mode 100644 index 0000000000..e6309df7eb --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.html @@ -0,0 +1,100 @@ + +
    + + {{'tb.rulenode.interval' | translate}} + + + {{'tb.rulenode.interval-required' | translate}} + + + {{'tb.rulenode.interval-min-error' | translate}} + + help + +
    +
    +
    tb.rulenode.strategy
    + + + {{ deduplicationStrategiesTranslations.get(strategy) | translate }} + + + + + + + + +
    + + +
    +
    +
    + + + tb.rulenode.advanced-settings + +
    + + {{'tb.rulenode.max-pending-msgs' | translate}} + + + {{'tb.rulenode.max-pending-msgs-required' | translate}} + + + {{'tb.rulenode.max-pending-msgs-max-error' | translate}} + + + {{'tb.rulenode.max-pending-msgs-min-error' | translate}} + + help + + + {{'tb.rulenode.max-retries' | translate}} + + + {{'tb.rulenode.max-retries-required' | translate}} + + + {{'tb.rulenode.max-retries-max-error' | translate}} + + + {{'tb.rulenode.max-retries-min-error' | translate}} + + help + +
    +
    +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.ts new file mode 100644 index 0000000000..ec9b3a9cf2 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.ts @@ -0,0 +1,79 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { deduplicationStrategiesTranslations, FetchMode } from '@home/components/rule-node/rule-node-config.models'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-action-node-msg-deduplication-config', + templateUrl: './deduplication-config.component.html', + styleUrls: [] +}) + +export class DeduplicationConfigComponent extends RuleNodeConfigurationComponent { + + deduplicationConfigForm: FormGroup; + deduplicationStrategie = FetchMode; + deduplicationStrategies = Object.keys(this.deduplicationStrategie); + deduplicationStrategiesTranslations = deduplicationStrategiesTranslations; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.deduplicationConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.deduplicationConfigForm = this.fb.group({ + interval: [isDefinedAndNotNull(configuration?.interval) ? configuration.interval : null, [Validators.required, + Validators.min(1)]], + strategy: [isDefinedAndNotNull(configuration?.strategy) ? configuration.strategy : null, [Validators.required]], + outMsgType: [isDefinedAndNotNull(configuration?.outMsgType) ? configuration.outMsgType : null, [Validators.required]], + maxPendingMsgs: [isDefinedAndNotNull(configuration?.maxPendingMsgs) ? configuration.maxPendingMsgs : null, [Validators.required, + Validators.min(1), Validators.max(1000)]], + maxRetries: [isDefinedAndNotNull(configuration?.maxRetries) ? configuration.maxRetries : null, + [Validators.required, Validators.min(0), Validators.max(100)]] + }); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (!configuration) { + configuration = {}; + } + if (!configuration.outMsgType) { + configuration.outMsgType = 'POST_TELEMETRY_REQUEST'; + } + return super.prepareInputConfig(configuration); + } + + protected updateValidators(emitEvent: boolean) { + if (this.deduplicationConfigForm.get('strategy').value === this.deduplicationStrategie.ALL) { + this.deduplicationConfigForm.get('outMsgType').enable({emitEvent: false}); + } else { + this.deduplicationConfigForm.get('outMsgType').disable({emitEvent: false}); + } + this.deduplicationConfigForm.get('outMsgType').updateValueAndValidity({emitEvent}); + } + + protected validatorTriggers(): string[] { + return ['strategy']; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.html new file mode 100644 index 0000000000..23737bab9f --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.html @@ -0,0 +1,35 @@ + +
    + + + + + help + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.ts new file mode 100644 index 0000000000..a5e95ef6ce --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.ts @@ -0,0 +1,74 @@ +/// +/// 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 { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { isDefinedAndNotNull } from '@core/public-api'; +import { TranslateService } from '@ngx-translate/core'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; +import { FetchTo, FetchToTranslation } from '@home/components/rule-node/rule-node-config.models'; + +@Component({ + selector: 'tb-transformation-node-delete-keys-config', + templateUrl: './delete-keys-config.component.html', + styleUrls: [] +}) + +export class DeleteKeysConfigComponent extends RuleNodeConfigurationComponent { + + deleteKeysConfigForm: FormGroup; + deleteFrom = []; + translation = FetchToTranslation; + + constructor(private fb: FormBuilder, + private translate: TranslateService) { + super(); + for (const key of this.translation.keys()) { + this.deleteFrom.push({ + value: key, + name: this.translate.instant(this.translation.get(key)) + }); + } + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.deleteKeysConfigForm = this.fb.group({ + deleteFrom: [configuration.deleteFrom, [Validators.required]], + keys: [configuration ? configuration.keys : null, [Validators.required]] + }); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + let deleteFrom: FetchTo; + + if (isDefinedAndNotNull(configuration?.fromMetadata)) { + deleteFrom = configuration.fromMetadata ? FetchTo.METADATA : FetchTo.DATA; + } else if (isDefinedAndNotNull(configuration?.deleteFrom)) { + deleteFrom = configuration?.deleteFrom; + } else { + deleteFrom = FetchTo.DATA; + } + + return { + keys: isDefinedAndNotNull(configuration?.keys) ? configuration.keys : null, + deleteFrom + }; + } + + protected configForm(): FormGroup { + return this.deleteKeysConfigForm; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.html new file mode 100644 index 0000000000..c1d3c8e2e4 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.html @@ -0,0 +1,25 @@ + +
    + + {{ 'tb.rulenode.json-path-expression' | translate }} + + {{ 'tb.rulenode.json-path-expression-hint' | translate }} + {{ 'tb.rulenode.json-path-expression-required' | translate }} + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.ts new file mode 100644 index 0000000000..47185b1d51 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.ts @@ -0,0 +1,44 @@ +/// +/// 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 { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + +@Component({ + selector: 'tb-transformation-node-json-path-config', + templateUrl: './node-json-path-config.component.html', + styleUrls: [] +}) + +export class NodeJsonPathConfigComponent extends RuleNodeConfigurationComponent { + + jsonPathConfigForm: FormGroup; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.jsonPathConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.jsonPathConfigForm = this.fb.group({ + jsonPath: [configuration ? configuration.jsonPath : null, [Validators.required]], + }); + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.html new file mode 100644 index 0000000000..3099a31e4e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.html @@ -0,0 +1,40 @@ + +
    +
    tb.rulenode.rename-keys-in
    +
    +
    + + + {{ data.name }} + + +
    +
    + + +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.scss new file mode 100644 index 0000000000..1c767d5d68 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.scss @@ -0,0 +1,27 @@ +/** + * 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 { + .fetch-to-data-toggle { + max-width: 420px; + width: 100%; + } + + .fx-centered { + display: flex; + width: 100%; + justify-content: space-around; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.ts new file mode 100644 index 0000000000..ebc7393b05 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.ts @@ -0,0 +1,73 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import { FetchTo, FetchToRenameTranslation } from '../rule-node-config.models'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; + + +@Component({ + selector: 'tb-transformation-node-rename-keys-config', + templateUrl: './rename-keys-config.component.html', + styleUrls: ['./rename-keys-config.component.scss'] +}) +export class RenameKeysConfigComponent extends RuleNodeConfigurationComponent { + renameKeysConfigForm: FormGroup; + renameIn = []; + translation = FetchToRenameTranslation; + + constructor(private fb: FormBuilder, + private translate: TranslateService) { + super(); + for (const key of this.translation.keys()) { + this.renameIn.push({ + value: key, + name: this.translate.instant(this.translation.get(key)) + }); + } + } + + protected configForm(): FormGroup { + return this.renameKeysConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.renameKeysConfigForm = this.fb.group({ + renameIn: [configuration ? configuration.renameIn : null, [Validators.required]], + renameKeysMapping: [configuration ? configuration.renameKeysMapping : null, [Validators.required]] + }); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + let renameIn: FetchTo; + + if (isDefinedAndNotNull(configuration?.fromMetadata)) { + renameIn = configuration.fromMetadata ? FetchTo.METADATA : FetchTo.DATA; + } else if (isDefinedAndNotNull(configuration?.renameIn)) { + renameIn = configuration?.renameIn; + } else { + renameIn = FetchTo.DATA; + } + + return { + renameKeysMapping: isDefinedAndNotNull(configuration?.renameKeysMapping) ? configuration.renameKeysMapping : null, + renameIn + }; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/rule-node-config-transform.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/transform/rule-node-config-transform.module.ts new file mode 100644 index 0000000000..c64381e54e --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/rule-node-config-transform.module.ts @@ -0,0 +1,70 @@ +/// +/// 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 { NgModule, Type } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { ChangeOriginatorConfigComponent } from './change-originator-config.component'; +import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.module'; +import { TransformScriptConfigComponent } from './script-config.component'; +import { ToEmailConfigComponent } from './to-email-config.component'; +import { CopyKeysConfigComponent } from './copy-keys-config.component'; +import { RenameKeysConfigComponent } from './rename-keys-config.component'; +import { NodeJsonPathConfigComponent } from './node-json-path-config.component'; +import { DeleteKeysConfigComponent } from './delete-keys-config.component'; +import { DeduplicationConfigComponent } from './deduplication-config.component'; +import { ScriptConfigComponent } from '@home/components/rule-node/filter/script-config.component'; + +@NgModule({ + declarations: [ + ChangeOriginatorConfigComponent, + TransformScriptConfigComponent, + ToEmailConfigComponent, + CopyKeysConfigComponent, + RenameKeysConfigComponent, + NodeJsonPathConfigComponent, + DeleteKeysConfigComponent, + DeduplicationConfigComponent + ], + imports: [ + CommonModule, + SharedModule, + RuleNodeConfigCommonModule + ], + exports: [ + ChangeOriginatorConfigComponent, + TransformScriptConfigComponent, + ToEmailConfigComponent, + CopyKeysConfigComponent, + RenameKeysConfigComponent, + NodeJsonPathConfigComponent, + DeleteKeysConfigComponent, + DeduplicationConfigComponent + ] +}) +export class RuleNodeConfigTransformModule { +} + +export const ruleNodeTransformConfigComponentsMap: Record> = { + 'tbTransformationNodeChangeOriginatorConfig': ChangeOriginatorConfigComponent, + 'tbTransformationNodeCopyKeysConfig': CopyKeysConfigComponent, + 'tbActionNodeMsgDeduplicationConfig': DeduplicationConfigComponent, + 'tbTransformationNodeDeleteKeysConfig': DeleteKeysConfigComponent, + 'tbTransformationNodeJsonPathConfig': NodeJsonPathConfigComponent, + 'tbTransformationNodeRenameKeysConfig': RenameKeysConfigComponent, + 'tbTransformationNodeScriptConfig': ScriptConfigComponent, + 'tbTransformationNodeToEmailConfig': ToEmailConfigComponent +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.html new file mode 100644 index 0000000000..efabc8d940 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.html @@ -0,0 +1,59 @@ + +
    + + + + + + + +
    + +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.ts new file mode 100644 index 0000000000..7e462ee039 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/script-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, EventEmitter, ViewChild } from '@angular/core'; +import { getCurrentAuthState, NodeScriptTestService } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { TranslateService } from '@ngx-translate/core'; +import type { JsFuncComponent } from '@shared/components/js-func.component'; +import { + RuleNodeConfiguration, + RuleNodeConfigurationComponent, + ScriptLanguage +} from '@app/shared/models/rule-node.models'; +import { DebugRuleNodeEventBody } from '@shared/models/event.models'; + +@Component({ + selector: 'tb-transformation-node-script-config', + templateUrl: './script-config.component.html', + styleUrls: [] +}) +export class TransformScriptConfigComponent extends RuleNodeConfigurationComponent { + + @ViewChild('jsFuncComponent', {static: false}) jsFuncComponent: JsFuncComponent; + @ViewChild('tbelFuncComponent', {static: false}) tbelFuncComponent: JsFuncComponent; + + scriptConfigForm: FormGroup; + + tbelEnabled = getCurrentAuthState(this.store).tbelEnabled; + + scriptLanguage = ScriptLanguage; + + changeScript: EventEmitter = new EventEmitter(); + + readonly hasScript = true; + + readonly testScriptLabel = 'tb.rulenode.test-transformer-function'; + + constructor(private fb: FormBuilder, + private nodeScriptTestService: NodeScriptTestService, + private translate: TranslateService) { + super(); + } + + protected configForm(): FormGroup { + return this.scriptConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.scriptConfigForm = this.fb.group({ + scriptLang: [configuration ? configuration.scriptLang : ScriptLanguage.JS, [Validators.required]], + jsScript: [configuration ? configuration.jsScript : null, [Validators.required]], + tbelScript: [configuration ? configuration.tbelScript : null, []] + }); + } + + protected validatorTriggers(): string[] { + return ['scriptLang']; + } + + protected updateValidators(emitEvent: boolean) { + let scriptLang: ScriptLanguage = this.scriptConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.TBEL && !this.tbelEnabled) { + scriptLang = ScriptLanguage.JS; + this.scriptConfigForm.get('scriptLang').patchValue(scriptLang, {emitEvent: false}); + setTimeout(() => { + this.scriptConfigForm.updateValueAndValidity({emitEvent: true}); + }); + } + this.scriptConfigForm.get('jsScript').setValidators(scriptLang === ScriptLanguage.JS ? [Validators.required] : []); + this.scriptConfigForm.get('jsScript').updateValueAndValidity({emitEvent}); + this.scriptConfigForm.get('tbelScript').setValidators(scriptLang === ScriptLanguage.TBEL ? [Validators.required] : []); + this.scriptConfigForm.get('tbelScript').updateValueAndValidity({emitEvent}); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + if (configuration) { + if (!configuration.scriptLang) { + configuration.scriptLang = ScriptLanguage.JS; + } + } + return configuration; + } + + testScript(debugEventBody?: DebugRuleNodeEventBody) { + const scriptLang: ScriptLanguage = this.scriptConfigForm.get('scriptLang').value; + const scriptField = scriptLang === ScriptLanguage.JS ? 'jsScript' : 'tbelScript'; + const helpId = scriptLang === ScriptLanguage.JS + ? 'rulenode/transformation_node_script_fn' + : 'rulenode/tbel/transformation_node_script_fn'; + const script: string = this.scriptConfigForm.get(scriptField).value; + this.nodeScriptTestService.testNodeScript( + script, + 'update', + this.translate.instant('tb.rulenode.transformer'), + 'Transform', + ['msg', 'metadata', 'msgType'], + this.ruleNodeId, + helpId, + scriptLang, + debugEventBody + ).subscribe((theScript) => { + if (theScript) { + this.scriptConfigForm.get(scriptField).setValue(theScript); + this.changeScript.emit(); + } + }); + } + + protected onValidate() { + const scriptLang: ScriptLanguage = this.scriptConfigForm.get('scriptLang').value; + if (scriptLang === ScriptLanguage.JS) { + this.jsFuncComponent.validateOnSubmit(); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.html new file mode 100644 index 0000000000..f28a6d4737 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.html @@ -0,0 +1,139 @@ + +
    +
    +
    tb.rulenode.email-sender
    +
    + + tb.rulenode.from-template + + + {{ 'tb.rulenode.email-from-template-hint' | translate }} + + +
    +
    +
    +
    + + {{ 'tb.rulenode.from-template-required' | translate }} + +
    +
    +
    +
    +
    +
    tb.rulenode.recipients
    + + +
    +
    + + tb.rulenode.to-template + + + {{ 'tb.rulenode.to-template-required' | translate }} + + + + tb.rulenode.cc-template + + + + tb.rulenode.bcc-template + + +
    +
    +
    +
    tb.rulenode.message-subject-and-content
    + + +
    + + tb.rulenode.subject-template + + + {{ 'tb.rulenode.subject-template-required' | translate }} + + + + tb.rulenode.mail-body-type + + + + {{ getBodyTypeName() | translate }} + + + + + {{ type.name | translate }} + +
    + + {{ type.description | translate }} + +
    +
    +
    + + tb.rulenode.body-type-template + + tb.mail-body-type.after-template-evaluation-hint + + + tb.rulenode.body-template + + + {{ 'tb.rulenode.body-template-required' | translate }} + + +
    +
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.scss new file mode 100644 index 0000000000..2a0c2e6ea3 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.scss @@ -0,0 +1,29 @@ +/** + * 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 { + .input-bottom-double-hint { + display: inline-flex; + + & .see-example { + flex-shrink: 0; + padding-right: 16px; + } + } + + textarea.tb-enable-vertical-resize { + resize: vertical; + } +} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.ts new file mode 100644 index 0000000000..3c922a7067 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.ts @@ -0,0 +1,98 @@ +/// +/// 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 { isDefinedAndNotNull } from '@core/public-api'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; + +@Component({ + selector: 'tb-transformation-node-to-email-config', + templateUrl: './to-email-config.component.html', + styleUrls: ['./to-email-config.component.scss'] +}) +export class ToEmailConfigComponent extends RuleNodeConfigurationComponent { + + toEmailConfigForm: FormGroup; + 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', + } + ]; + + constructor(private fb: FormBuilder) { + super(); + } + + protected configForm(): FormGroup { + return this.toEmailConfigForm; + } + + protected onConfigurationSet(configuration: RuleNodeConfiguration) { + this.toEmailConfigForm = this.fb.group({ + fromTemplate: [configuration ? configuration.fromTemplate : null, [Validators.required]], + toTemplate: [configuration ? configuration.toTemplate : null, [Validators.required]], + ccTemplate: [configuration ? configuration.ccTemplate : null, []], + bccTemplate: [configuration ? configuration.bccTemplate : null, []], + subjectTemplate: [configuration ? configuration.subjectTemplate : null, [Validators.required]], + mailBodyType: [configuration ? configuration.mailBodyType : null], + isHtmlTemplate: [configuration ? configuration.isHtmlTemplate : null, [Validators.required]], + bodyTemplate: [configuration ? configuration.bodyTemplate : null, [Validators.required]], + }); + } + + protected prepareInputConfig(configuration: RuleNodeConfiguration): RuleNodeConfiguration { + return { + fromTemplate: isDefinedAndNotNull(configuration?.fromTemplate) ? configuration.fromTemplate : null, + toTemplate: isDefinedAndNotNull(configuration?.toTemplate) ? configuration.toTemplate : null, + ccTemplate: isDefinedAndNotNull(configuration?.ccTemplate) ? configuration.ccTemplate : null, + bccTemplate: isDefinedAndNotNull(configuration?.bccTemplate) ? configuration.bccTemplate : null, + subjectTemplate: isDefinedAndNotNull(configuration?.subjectTemplate) ? configuration.subjectTemplate : null, + mailBodyType: isDefinedAndNotNull(configuration?.mailBodyType) ? configuration.mailBodyType : null, + isHtmlTemplate: isDefinedAndNotNull(configuration?.isHtmlTemplate) ? configuration.isHtmlTemplate : null, + bodyTemplate: isDefinedAndNotNull(configuration?.bodyTemplate) ? configuration.bodyTemplate : null, + }; + } + + protected updateValidators(emitEvent: boolean) { + if (this.toEmailConfigForm.get('mailBodyType').value === 'dynamic') { + this.toEmailConfigForm.get('isHtmlTemplate').enable({emitEvent: false}); + } else { + this.toEmailConfigForm.get('isHtmlTemplate').disable({emitEvent: false}); + } + this.toEmailConfigForm.get('isHtmlTemplate').updateValueAndValidity({emitEvent}); + } + + protected validatorTriggers(): string[] { + return ['mailBodyType']; + } + + getBodyTypeName(): string { + return this.mailBodyTypes.find(type => type.value === this.toEmailConfigForm.get('mailBodyType').value).name; + } +} diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts index fc73cc9d56..029c4b5547 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts @@ -21,7 +21,7 @@ import { forwardRef, Input, OnDestroy, - Output, + Output, Type, ViewChild, ViewContainerRef } from '@angular/core'; @@ -43,6 +43,7 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { JsonObjectEditComponent } from '@shared/components/json-object-edit.component'; import { deepClone } from '@core/utils'; import { RuleChainType } from '@shared/models/rule-chain.models'; +import { ruleNodeConfigComponentsMap } from '@home/components/rule-node/rule-node-config.module'; @Component({ selector: 'tb-rule-node-config', @@ -207,8 +208,17 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnDestroy this.changeSubscription.unsubscribe(); this.changeSubscription = null; } + if (this.changeScriptSubscription) { + this.changeScriptSubscription.unsubscribe(); + this.changeScriptSubscription = null; + } this.definedConfigContainer.clear(); - const component = this.ruleChainService.getRuleNodeConfigComponent(this.nodeDefinition.configDirective); + let component: Type; + if (!this.nodeDefinition.uiResources?.length) { + component = ruleNodeConfigComponentsMap[this.nodeDefinition.configDirective]; + } else { + component = this.ruleChainService.getRuleNodeConfigComponent(this.nodeDefinition.configDirective); + } this.definedConfigComponentRef = this.definedConfigContainer.createComponent(component); this.definedConfigComponent = this.definedConfigComponentRef.instance; this.definedConfigComponent.ruleNodeId = this.ruleNodeId; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.module.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.module.ts index 4cc83b0074..00fa560382 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.module.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.module.ts @@ -34,6 +34,7 @@ import { LinkLabelsComponent } from '@home/pages/rulechain/link-labels.component import { RuleNodeConfigComponent } from './rule-node-config.component'; import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe'; import { EntityDebugSettingsButtonComponent } from '@home/components/entity/debug/entity-debug-settings-button.component'; +import { RuleNodeConfigModule } from '@home/components/rule-node/rule-node-config.module'; @NgModule({ declarations: [ @@ -63,7 +64,8 @@ import { EntityDebugSettingsButtonComponent } from '@home/components/entity/debu HomeComponentsModule, RuleChainRoutingModule, DurationLeftPipe, - EntityDebugSettingsButtonComponent + EntityDebugSettingsButtonComponent, + RuleNodeConfigModule, ] }) export class RuleChainModule { } diff --git a/ui-ngx/src/app/shared/models/rule-node.models.ts b/ui-ngx/src/app/shared/models/rule-node.models.ts index a79fdbc376..86e304b3df 100644 --- a/ui-ngx/src/app/shared/models/rule-node.models.ts +++ b/ui-ngx/src/app/shared/models/rule-node.models.ts @@ -21,9 +21,7 @@ import { ComponentDescriptor } from '@shared/models/component-descriptor.models' import { FcEdge, FcNode } from 'ngx-flowchart'; import { Observable } from 'rxjs'; import { PageComponent } from '@shared/components/page.component'; -import { AfterViewInit, EventEmitter, Inject, OnInit, Directive, DestroyRef, inject } from '@angular/core'; -import { Store } from '@ngrx/store'; -import { AppState } from '@core/core.state'; +import { AfterViewInit, DestroyRef, Directive, EventEmitter, inject, OnInit } from '@angular/core'; import { AbstractControl, UntypedFormGroup } from '@angular/forms'; import { RuleChainType } from '@shared/models/rule-chain.models'; import { DebugRuleNodeEventBody } from '@shared/models/event.models'; @@ -134,8 +132,8 @@ export abstract class RuleNodeConfigurationComponent extends PageComponent imple configurationChangedEmiter = new EventEmitter(); configurationChanged = this.configurationChangedEmiter.asObservable(); - protected constructor(@Inject(Store) protected store: Store) { - super(store); + protected constructor(...args: unknown[]) { + super(); } ngOnInit() {} 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 427fbdbe14..bbcc04d5f9 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4481,6 +4481,734 @@ "too-many-requests": "Too many requests", "too-many-updates": "Too many updates" }, + "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.", + "max-relation-level-invalid": "Value should be an integer.", + "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", + "fields-mapping-hint": "If the message field is set to $entityId, the message originator's id will be saved to the specified table column.", + "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.", + "default-ttl-zero-hint": "TTL will not be applied if its value is set to 0.", + "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": "Period in seconds", + "period-seconds-required": "Period is required.", + "generation-frequency-seconds": "Generation frequency in seconds", + "generation-frequency-required": "Generation frequency is required.", + "min-generation-frequency-message": "Only 1 second minimum is allowed.", + "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", + "current-tenant": "Current Tenant", + "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.", + "memory-buffer-size-range": "Memory buffer size must be between 0 and {{max}} KB", + "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.", + "int-range": "Value must not exceed the maximum integer limit (2147483648)", + "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": "The table must be created in your Cassandra cluster and its name must start with the prefix 'cs_tb_' to avoid the data insertion to the common TB tables. Enter the table name here without the 'cs_tb_' prefix.", + "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." + } + }, "tenant": { "tenant": "Tenant", "tenants": "Tenants", From 038dea7810f12fee60fc5186a3d2e69a5426b218 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 8 Jan 2025 15:08:13 +0200 Subject: [PATCH 02/13] UI: Rename rule node modules and component --- .../deduplication/TbMsgDeduplicationNode.java | 2 +- .../engine/profile/TbDeviceProfileNode.java | 2 +- ...e.ts => action-rule-node-config.module.ts} | 11 ++-- .../action/device-profile-config.component.ts | 2 +- .../action/device-state-config.component.ts | 7 ++- ...e.ts => common-rule-node-config.module.ts} | 2 +- ...ts => enrichment-rule-node-core.module.ts} | 8 +-- ...ts => external-rule-node-config.module.ts} | 8 +-- ...e.ts => filter-rule-node-config.module.ts} | 8 +-- .../filter/message-type-config.component.ts | 3 +- ...ule.ts => flow-rule-node-config.module.ts} | 4 +- .../rule-node/rule-node-config.module.ts | 60 +++++++++---------- .../change-originator-config.component.html | 2 +- .../change-originator-config.component.ts | 0 .../copy-keys-config.component.html | 0 .../copy-keys-config.component.ts | 0 .../deduplication-config.component.html | 0 .../deduplication-config.component.ts | 2 +- .../delete-keys-config.component.html | 0 .../delete-keys-config.component.ts | 0 .../node-json-path-config.component.html | 0 .../node-json-path-config.component.ts | 0 .../rename-keys-config.component.html | 0 .../rename-keys-config.component.scss | 0 .../rename-keys-config.component.ts | 0 .../script-config.component.html | 0 .../script-config.component.ts | 0 .../to-email-config.component.html | 0 .../to-email-config.component.scss | 0 .../to-email-config.component.ts | 0 ...transformation-rule-node-config.module.ts} | 10 ++-- .../assets/locale/locale.constant-en_US.json | 2 +- 32 files changed, 68 insertions(+), 65 deletions(-) rename ui-ngx/src/app/modules/home/components/rule-node/action/{rule-node-config-action.module.ts => action-rule-node-config.module.ts} (93%) rename ui-ngx/src/app/modules/home/components/rule-node/common/{rule-node-config-common.module.ts => common-rule-node-config.module.ts} (98%) rename ui-ngx/src/app/modules/home/components/rule-node/enrichment/{rule-node-core-enrichment.module.ts => enrichment-rule-node-core.module.ts} (93%) rename ui-ngx/src/app/modules/home/components/rule-node/external/{rule-node-config-external.module.ts => external-rule-node-config.module.ts} (93%) rename ui-ngx/src/app/modules/home/components/rule-node/filter/{rule-node-config-filter.module.ts => filter-rule-node-config.module.ts} (92%) rename ui-ngx/src/app/modules/home/components/rule-node/flow/{rule-node-config-flow.module.ts => flow-rule-node-config.module.ts} (92%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/change-originator-config.component.html (98%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/change-originator-config.component.ts (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/copy-keys-config.component.html (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/copy-keys-config.component.ts (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/deduplication-config.component.html (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/deduplication-config.component.ts (98%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/delete-keys-config.component.html (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/delete-keys-config.component.ts (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/node-json-path-config.component.html (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/node-json-path-config.component.ts (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/rename-keys-config.component.html (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/rename-keys-config.component.scss (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/rename-keys-config.component.ts (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/script-config.component.html (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/script-config.component.ts (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/to-email-config.component.html (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/to-email-config.component.scss (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform => transformation}/to-email-config.component.ts (100%) rename ui-ngx/src/app/modules/home/components/rule-node/{transform/rule-node-config-transform.module.ts => transformation/transformation-rule-node-config.module.ts} (88%) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java index 891efec861..6d13332f6f 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/deduplication/TbMsgDeduplicationNode.java @@ -59,7 +59,7 @@ import static org.thingsboard.server.common.data.DataConstants.QUEUE_NAME; "
  • ALL - return all messages as a single JSON array message. " + "Where each element represents object with msg and metadata inner properties.
  • ", icon = "content_copy", - configDirective = "tbActionNodeMsgDeduplicationConfig" + configDirective = "tbTransformationNodeDeduplicationConfig" ) @Slf4j public class TbMsgDeduplicationNode implements TbNode { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java index 9df674cf88..40fa08ae3c 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java @@ -59,7 +59,7 @@ import java.util.concurrent.TimeUnit; nodeDescription = "Process device messages based on device profile settings", nodeDetails = "Create and clear alarms based on alarm rules defined in device profile. The output relation type is either " + "'Alarm Created', 'Alarm Updated', 'Alarm Severity Updated' and 'Alarm Cleared' or simply 'Success' if no alarms were affected.", - configDirective = "tbDeviceProfileConfig" + configDirective = "tbActionNodeDeviceProfileConfig" ) public class TbDeviceProfileNode implements TbNode { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/rule-node-config-action.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts similarity index 93% rename from ui-ngx/src/app/modules/home/components/rule-node/action/rule-node-config-action.module.ts rename to ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts index 8c8350378d..3e78ee4c46 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/rule-node-config-action.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts @@ -33,7 +33,7 @@ import { GpsGeoActionConfigComponent } from './gps-geo-action-config.component'; import { MsgCountConfigComponent } from './msg-count-config.component'; import { RpcReplyConfigComponent } from './rpc-reply-config.component'; import { SaveToCustomTableConfigComponent } from './save-to-custom-table-config.component'; -import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.module'; +import { CommonRuleNodeConfigModule } from '../common/common-rule-node-config.module'; import { UnassignCustomerConfigComponent } from './unassign-customer-config.component'; import { DeviceProfileConfigComponent } from './device-profile-config.component'; import { PushToEdgeConfigComponent } from './push-to-edge-config.component'; @@ -42,7 +42,6 @@ import { DeleteAttributesConfigComponent } from './delete-attributes-config.comp import { MathFunctionConfigComponent } from './math-function-config.component'; import { DeviceStateConfigComponent } from './device-state-config.component'; import { SendRestApiCallReplyConfigComponent } from './send-rest-api-call-reply-config.component'; -import { EmptyConfigComponent } from '@home/components/rule-node/empty-config.component'; @NgModule({ declarations: [ @@ -74,7 +73,7 @@ import { EmptyConfigComponent } from '@home/components/rule-node/empty-config.co CommonModule, SharedModule, HomeComponentsModule, - RuleNodeConfigCommonModule + CommonRuleNodeConfigModule ], exports: [ DeleteAttributesConfigComponent, @@ -102,10 +101,10 @@ import { EmptyConfigComponent } from '@home/components/rule-node/empty-config.co DeviceStateConfigComponent ] }) -export class RuleNodeConfigActionModule { +export class ActionRuleNodeConfigModule { } -export const ruleNodeActionConfigComponentsMap: Record> = { +export const actionRuleNodeConfigComponentsMap: Record> = { 'tbActionNodeAssignToCustomerConfig': AssignCustomerConfigComponent, 'tbActionNodeAttributesConfig': AttributesConfigComponent, 'tbActionNodeClearAlarmConfig': ClearAlarmConfigComponent, @@ -113,7 +112,7 @@ export const ruleNodeActionConfigComponentsMap: Record> = { +export const enrichmentRuleNodeConfigComponentsMap: Record> = { 'tbEnrichmentNodeCalculateDeltaConfig': CalculateDeltaConfigComponent, 'tbEnrichmentNodeCustomerAttributesConfig': CustomerAttributesConfigComponent, 'tbEnrichmentNodeDeviceAttributesConfig': DeviceAttributesConfigComponent, diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rule-node-config-external.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts similarity index 93% rename from ui-ngx/src/app/modules/home/components/rule-node/external/rule-node-config-external.module.ts rename to ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts index c170d9ccd6..38395b9dac 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/rule-node-config-external.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts @@ -29,7 +29,7 @@ import { SendSmsConfigComponent } from './send-sms-config.component'; import { CommonModule } from '@angular/common'; import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; import { HomeComponentsModule } from '@home/components/public-api'; -import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.module'; +import { CommonRuleNodeConfigModule } from '../common/common-rule-node-config.module'; import { SlackConfigComponent } from './slack-config.component'; import { LambdaConfigComponent } from './lambda-config.component'; @@ -53,7 +53,7 @@ import { LambdaConfigComponent } from './lambda-config.component'; CommonModule, SharedModule, HomeComponentsModule, - RuleNodeConfigCommonModule + CommonRuleNodeConfigModule ], exports: [ SnsConfigComponent, @@ -71,10 +71,10 @@ import { LambdaConfigComponent } from './lambda-config.component'; SlackConfigComponent ] }) -export class RuleNodeConfigExternalModule { +export class ExternalRuleNodeConfigModule { } -export const ruleNodeExternalConfigComponentsMap: Record> = { +export const externalRuleNodeConfigComponentsMap: Record> = { 'tbExternalNodeAzureIotHubConfig': AzureIotHubConfigComponent, 'tbExternalNodeKafkaConfig': KafkaConfigComponent, 'tbExternalNodeLambdaConfig': LambdaConfigComponent, diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/rule-node-config-filter.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts similarity index 92% rename from ui-ngx/src/app/modules/home/components/rule-node/filter/rule-node-config-filter.module.ts rename to ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts index 52ad3169d5..ca0aaffd71 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/rule-node-config-filter.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts @@ -25,7 +25,7 @@ import { OriginatorTypeConfigComponent } from './originator-type-config.componen import { ScriptConfigComponent } from './script-config.component'; import { SwitchConfigComponent } from './switch-config.component'; import { CheckAlarmStatusComponent } from './check-alarm-status.component'; -import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.module'; +import { CommonRuleNodeConfigModule } from '../common/common-rule-node-config.module'; @NgModule({ declarations: [ @@ -41,7 +41,7 @@ import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.mo imports: [ CommonModule, SharedModule, - RuleNodeConfigCommonModule + CommonRuleNodeConfigModule ], exports: [ CheckMessageConfigComponent, @@ -54,10 +54,10 @@ import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.mo CheckAlarmStatusComponent ] }) -export class RuleNodeConfigFilterModule { +export class FilterRuleNodeConfigModule { } -export const ruleNodeFilterConfigComponentsMap: Record> = { +export const filterRuleNodeConfigComponentsMap: Record> = { 'tbFilterNodeCheckAlarmStatusConfig': CheckAlarmStatusComponent, 'tbFilterNodeCheckMessageConfig': CheckMessageConfigComponent, 'tbFilterNodeCheckRelationConfig': CheckRelationConfigComponent, diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts index 0f8392c4f0..61cc018aab 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.ts @@ -15,8 +15,7 @@ /// import { Component } from '@angular/core'; -import { AppState, isDefinedAndNotNull } from '@core/public-api'; -import { Store } from '@ngrx/store'; +import { isDefinedAndNotNull } from '@core/public-api'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-node-config-flow.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts similarity index 92% rename from ui-ngx/src/app/modules/home/components/rule-node/flow/rule-node-config-flow.module.ts rename to ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts index 4dae3212aa..2ee36f71fc 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-node-config-flow.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts @@ -34,10 +34,10 @@ import { RuleChainOutputComponent } from './rule-chain-output.component'; RuleChainOutputComponent ] }) -export class RuleNodeConfigFlowModule { +export class FlowRuleNodeConfigModule { } -export const ruleNodeFlowConfigComponentsMap: Record> = { +export const flowRuleNodeConfigComponentsMap: Record> = { 'tbFlowNodeRuleChainInputConfig': RuleChainInputComponent, 'tbFlowNodeRuleChainOutputConfig': RuleChainOutputComponent } diff --git a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts index 79d46f02d5..58efd925db 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts @@ -19,29 +19,29 @@ import { EmptyConfigComponent } from './empty-config.component'; import { CommonModule } from '@angular/common'; import { SharedModule } from '@shared/shared.module'; import { - ruleNodeActionConfigComponentsMap, - RuleNodeConfigActionModule -} from '@home/components/rule-node/action/rule-node-config-action.module'; + actionRuleNodeConfigComponentsMap, + ActionRuleNodeConfigModule +} from '@home/components/rule-node/action/action-rule-node-config.module'; import { - RuleNodeConfigFilterModule, - ruleNodeFilterConfigComponentsMap -} from '@home/components/rule-node/filter/rule-node-config-filter.module'; + filterRuleNodeConfigComponentsMap, + FilterRuleNodeConfigModule +} from '@home/components/rule-node/filter/filter-rule-node-config.module'; import { - RuleNodeCoreEnrichmentModule, - ruleNodeEnrichmentConfigComponentsMap -} from '@home/components/rule-node/enrichment/rule-node-core-enrichment.module'; + enrichmentRuleNodeConfigComponentsMap, + EnrichmentRuleNodeCoreModule +} from '@home/components/rule-node/enrichment/enrichment-rule-node-core.module'; import { - RuleNodeConfigExternalModule, - ruleNodeExternalConfigComponentsMap -} from '@home/components/rule-node/external/rule-node-config-external.module'; + externalRuleNodeConfigComponentsMap, + ExternalRuleNodeConfigModule +} from '@home/components/rule-node/external/external-rule-node-config.module'; import { - RuleNodeConfigTransformModule, - ruleNodeTransformConfigComponentsMap -} from '@home/components/rule-node/transform/rule-node-config-transform.module'; + transformationRuleNodeConfigComponentsMap, + TransformationRuleNodeConfigModule +} from '@home/components/rule-node/transformation/transformation-rule-node-config.module'; import { - RuleNodeConfigFlowModule, - ruleNodeFlowConfigComponentsMap -} from '@home/components/rule-node/flow/rule-node-config-flow.module'; + flowRuleNodeConfigComponentsMap, + FlowRuleNodeConfigModule +} from '@home/components/rule-node/flow/flow-rule-node-config.module'; import { IRuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @NgModule({ @@ -53,23 +53,23 @@ import { IRuleNodeConfigurationComponent } from '@shared/models/rule-node.models SharedModule ], exports: [ - RuleNodeConfigActionModule, - RuleNodeConfigFilterModule, - RuleNodeCoreEnrichmentModule, - RuleNodeConfigExternalModule, - RuleNodeConfigTransformModule, - RuleNodeConfigFlowModule, + ActionRuleNodeConfigModule, + FilterRuleNodeConfigModule, + EnrichmentRuleNodeCoreModule, + ExternalRuleNodeConfigModule, + TransformationRuleNodeConfigModule, + FlowRuleNodeConfigModule, EmptyConfigComponent ] }) export class RuleNodeConfigModule {} export const ruleNodeConfigComponentsMap: Record> = { - ...ruleNodeActionConfigComponentsMap, - ...ruleNodeEnrichmentConfigComponentsMap, - ...ruleNodeExternalConfigComponentsMap, - ...ruleNodeFilterConfigComponentsMap, - ...ruleNodeFlowConfigComponentsMap, - ...ruleNodeTransformConfigComponentsMap, + ...actionRuleNodeConfigComponentsMap, + ...enrichmentRuleNodeConfigComponentsMap, + ...externalRuleNodeConfigComponentsMap, + ...filterRuleNodeConfigComponentsMap, + ...flowRuleNodeConfigComponentsMap, + ...transformationRuleNodeConfigComponentsMap, 'tbNodeEmptyConfig': EmptyConfigComponent }; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/change-originator-config.component.html similarity index 98% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.html rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/change-originator-config.component.html index 818ea5a12d..1f66108e48 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/change-originator-config.component.html @@ -36,7 +36,7 @@
    + *ngIf="changeOriginatorConfigForm.get('originatorSource').value === originatorSource.ENTITY"> diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/change-originator-config.component.ts similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/change-originator-config.component.ts rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/change-originator-config.component.ts diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.html rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.html diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.ts similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/copy-keys-config.component.ts rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.ts diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.html rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.ts similarity index 98% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.ts rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.ts index ec9b3a9cf2..bf50b36f3a 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transform/deduplication-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.ts @@ -21,7 +21,7 @@ import { deduplicationStrategiesTranslations, FetchMode } from '@home/components import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; @Component({ - selector: 'tb-action-node-msg-deduplication-config', + selector: 'tb-transformation-node-deduplication-config', templateUrl: './deduplication-config.component.html', styleUrls: [] }) diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.html rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.html diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.ts similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/delete-keys-config.component.ts rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.ts diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.html rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.html diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.ts similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/node-json-path-config.component.ts rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.ts diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.html rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.html diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.scss similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.scss rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.scss diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.ts similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/rename-keys-config.component.ts rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.ts diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.html rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.html diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/script-config.component.ts rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.html rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.scss b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.scss similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.scss rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.scss diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts similarity index 100% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/to-email-config.component.ts rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transform/rule-node-config-transform.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts similarity index 88% rename from ui-ngx/src/app/modules/home/components/rule-node/transform/rule-node-config-transform.module.ts rename to ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts index c64381e54e..a25495d7b4 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transform/rule-node-config-transform.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts @@ -18,7 +18,7 @@ import { NgModule, Type } from '@angular/core'; import { CommonModule } from '@angular/common'; import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; import { ChangeOriginatorConfigComponent } from './change-originator-config.component'; -import { RuleNodeConfigCommonModule } from '../common/rule-node-config-common.module'; +import { CommonRuleNodeConfigModule } from '../common/common-rule-node-config.module'; import { TransformScriptConfigComponent } from './script-config.component'; import { ToEmailConfigComponent } from './to-email-config.component'; import { CopyKeysConfigComponent } from './copy-keys-config.component'; @@ -42,7 +42,7 @@ import { ScriptConfigComponent } from '@home/components/rule-node/filter/script- imports: [ CommonModule, SharedModule, - RuleNodeConfigCommonModule + CommonRuleNodeConfigModule ], exports: [ ChangeOriginatorConfigComponent, @@ -55,13 +55,13 @@ import { ScriptConfigComponent } from '@home/components/rule-node/filter/script- DeduplicationConfigComponent ] }) -export class RuleNodeConfigTransformModule { +export class TransformationRuleNodeConfigModule { } -export const ruleNodeTransformConfigComponentsMap: Record> = { +export const transformationRuleNodeConfigComponentsMap: Record> = { 'tbTransformationNodeChangeOriginatorConfig': ChangeOriginatorConfigComponent, 'tbTransformationNodeCopyKeysConfig': CopyKeysConfigComponent, - 'tbActionNodeMsgDeduplicationConfig': DeduplicationConfigComponent, + 'tbTransformationNodeDeduplicationConfig': DeduplicationConfigComponent, 'tbTransformationNodeDeleteKeysConfig': DeleteKeysConfigComponent, 'tbTransformationNodeJsonPathConfig': NodeJsonPathConfigComponent, 'tbTransformationNodeRenameKeysConfig': RenameKeysConfigComponent, 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 bbcc04d5f9..cbae98683c 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4927,7 +4927,7 @@ "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.", + "separator-hint": "You should press \"Enter\" to complete field input.", "select-details": "Select details", "entity-details-id": "Id", "entity-details-title": "Title", From 107f7237a9647cc28c581250abe9f15009cbc482 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 8 Jan 2025 17:36:25 +0200 Subject: [PATCH 03/13] UI: Remove rule node unnecessary translate pipe --- .../common/device-relations-query-config.component.html | 2 +- .../rule-node/common/select-attributes.component.html | 2 +- .../get-telemetry-from-database-config.component.html | 2 +- .../transformation/deduplication-config.component.html | 6 +++--- .../rule-node/transformation/to-email-config.component.html | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.html index 56d8c948d9..902ce3efc4 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.html @@ -16,7 +16,7 @@ -->
    -
    +
    relation.direction diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html index ab7bea5409..06d63535e9 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html @@ -16,7 +16,7 @@ -->
    - -
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html index e6309df7eb..5d5ec40580 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html @@ -37,14 +37,14 @@ {{ deduplicationStrategiesTranslations.get(strategy) | translate }} - - - diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html index f28a6d4737..87106d836d 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html @@ -45,7 +45,7 @@
    tb.rulenode.recipients
    -
    @@ -82,7 +82,7 @@
    tb.rulenode.message-subject-and-content
    -
    From f57d46af3727908cf2cbba43457600920351b158 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 8 Jan 2025 17:36:38 +0200 Subject: [PATCH 04/13] UI: Remove rulenode-core-config.js --- .../resources/public/static/rulenode/rulenode-core-config.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js 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 deleted file mode 100644 index 2ad9ac666b..0000000000 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ /dev/null @@ -1 +0,0 @@ -System.register(["@angular/core","@shared/public-api","@ngrx/store","@angular/forms","@core/public-api","@ngx-translate/core","@angular/cdk/keycodes","@angular/common","@home/components/public-api","tslib","rxjs","@angular/cdk/coercion","rxjs/operators"],(function(e){"use strict";var t,n,r,a,i,o,l,s,p,m,d,u,c,f,g,h,y,b,v,x,C,S,T,I,E,F,q,A,k,N,w,M,B,V,O,D,L,P,R,_,j,G,K,U,H,z,$,Q,J,Y,W,X,Z,ee,te,ne,re,ae,ie;return{setters:[function(e){t=e,n=e.EventEmitter,r=e.forwardRef,a=e.ɵNG_COMP_DEF},function(e){i=e.RuleNodeConfigurationComponent,o=e.AttributeScope,l=e.telemetryTypeTranslations,s=e.ScriptLanguage,p=e.AlarmSeverity,m=e.alarmSeverityTranslations,d=e.EntitySearchDirection,u=e.EntityType,c=e.entityFields,f=e.messageTypeNames,g=e.MessageType,h=e.coerceBoolean,y=e.PageComponent,b=e.entitySearchDirectionTranslations,v=e,x=e.AlarmStatus,C=e.alarmStatusTranslations,S=e.SharedModule,T=e.AggregationType,I=e.aggregationTranslations,E=e.NotificationType,F=e.SlackChanelType,q=e.SlackChanelTypesTranslateMap},function(e){A=e},function(e){k=e,N=e.Validators,w=e.FormArray,M=e.FormGroup,B=e.NgControl,V=e.NG_VALUE_ACCESSOR,O=e.NG_VALIDATORS},function(e){D=e.getCurrentAuthState,L=e,P=e.isDefinedAndNotNull,R=e.isEqual,_=e.deepTrim,j=e.isObject,G=e.isNotEmptyStr},function(e){K=e},function(e){U=e.ENTER,H=e.COMMA,z=e.SEMICOLON},function(e){$=e.CommonModule},function(e){Q=e.HomeComponentsModule},function(e){J=e.__decorate},function(e){Y=e.Subject,W=e.takeUntil,X=e.of},function(e){Z=e.coerceBooleanProperty},function(e){ee=e.startWith,te=e.map,ne=e.mergeMap,re=e.share,ae=e.tap,ie=e.takeUntil}],execute:function(){class oe extends i{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.emptyConfigForm}onConfigurationSet(e){this.emptyConfigForm=this.fb.group({})}static{this.ɵfac=function(e){return new(e||oe)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:oe,selectors:[["tb-node-empty-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:1,vars:0,template:function(e,n){1&e&&t.ɵɵelement(0,"div")},dependencies:t.ɵɵgetComponentDepsFactory(oe),encapsulation:2})}}function le(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.customer-name-pattern-required")," "))}e("EmptyConfigComponent",oe);class se extends i{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,[N.required,N.pattern(/.*\S.*/)]],createCustomerIfNotExists:[!!e&&e.createCustomerIfNotExists,[]]})}prepareOutputConfig(e){return e.customerNamePattern=e.customerNamePattern.trim(),e}static{this.ɵfac=function(e){return new(e||se)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:se,selectors:[["tb-action-node-assign-to-customer-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:13,vars:5,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"tb-form-panel","no-padding","no-border"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","customerNamePattern"],[4,"ngIf"],[1,"tb-form-row"],["formControlName","createCustomerIfNotExists",1,"mat-slide"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"mat-form-field",2)(3,"mat-label",3),t.ɵɵtext(4,"tb.rulenode.customer-name-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(5,"input",4),t.ɵɵtemplate(6,le,3,3,"mat-error",5),t.ɵɵelementStart(7,"mat-hint",3),t.ɵɵtext(8,"tb.rulenode.customer-name-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(9,"div",6)(10,"mat-slide-toggle",7),t.ɵɵtext(11),t.ɵɵpipe(12,"translate"),t.ɵɵelementEnd()()()()),2&e&&(t.ɵɵproperty("formGroup",n.assignCustomerConfigForm),t.ɵɵadvance(6),t.ɵɵproperty("ngIf",n.assignCustomerConfigForm.get("customerNamePattern").hasError("required")||n.assignCustomerConfigForm.get("customerNamePattern").hasError("pattern")),t.ɵɵadvance(5),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(12,3,"tb.rulenode.create-customer-if-not-exists")," "))},dependencies:t.ɵɵgetComponentDepsFactory(se),encapsulation:2})}}e("AssignCustomerConfigComponent",se);const pe=()=>({standalone:!0});function me(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",15),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.telemetryTypeTranslationsMap.get(e))," ")}}function de(e,n){1&e&&(t.ɵɵelementStart(0,"div",12),t.ɵɵpipe(1,"translate"),t.ɵɵelementStart(2,"mat-slide-toggle",16),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(1,2,"tb.rulenode.send-attributes-updated-notification-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(4,4,"tb.rulenode.send-attributes-updated-notification")," "))}function ue(e,n){1&e&&(t.ɵɵelementStart(0,"div",12),t.ɵɵpipe(1,"translate"),t.ɵɵelementStart(2,"mat-slide-toggle",17),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(1,2,"tb.rulenode.notify-device-on-update-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(4,4,"tb.rulenode.notify-device")," "))}class ce extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=o,this.attributeScopes=Object.keys(o),this.telemetryTypeTranslationsMap=l}configForm(){return this.attributesConfigForm}onConfigurationSet(e){this.attributesConfigForm=this.fb.group({scope:[e?e.scope:null,[N.required]],notifyDevice:[!e||e.notifyDevice,[]],sendAttributesUpdatedNotification:[!!e&&e.sendAttributesUpdatedNotification,[]],updateAttributesOnlyOnValueChange:[!!e&&e.updateAttributesOnlyOnValueChange,[]]}),this.attributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==o.SHARED_SCOPE&&this.attributesConfigForm.get("notifyDevice").patchValue(!1,{emitEvent:!1}),e===o.CLIENT_SCOPE&&this.attributesConfigForm.get("sendAttributesUpdatedNotification").patchValue(!1,{emitEvent:!1}),this.attributesConfigForm.get("updateAttributesOnlyOnValueChange").patchValue(!1,{emitEvent:!1})}))}static{this.ɵfac=function(e){return new(e||ce)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:ce,selectors:[["tb-action-node-attributes-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:31,vars:24,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],[1,"tb-form-panel","stroked"],[3,"hintText"],[1,"tb-form-row","no-border","no-padding","tb-standard-fields"],[1,"flex"],["required","","matInput","","formControlName","scope",1,"tb-entity-type-select"],[3,"value",4,"ngFor","ngForOf"],["type","text","matInput","","readonly","","disabled","",3,"ngModel","ngModelOptions"],["type","button","matSuffix","","mat-icon-button","","aria-label","Copy","ngxClipboard","",3,"cbContent","matTooltip"],["aria-hidden","false","aria-label","help-icon"],[1,"tb-settings"],["translate",""],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","updateAttributesOnlyOnValueChange",1,"mat-slide"],["class","tb-form-row no-border no-padding",3,"tb-hint-tooltip-icon",4,"ngIf"],[3,"value"],["formControlName","sendAttributesUpdatedNotification",1,"mat-slide"],["formControlName","notifyDevice",1,"mat-slide"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵelement(2,"tb-example-hint",2),t.ɵɵelementStart(3,"div",3)(4,"mat-form-field",4)(5,"mat-label"),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-select",5),t.ɵɵtemplate(9,me,3,4,"mat-option",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(10,"mat-form-field",4)(11,"mat-label"),t.ɵɵtext(12),t.ɵɵpipe(13,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(14,"input",7),t.ɵɵelementStart(15,"button",8),t.ɵɵpipe(16,"translate"),t.ɵɵelementStart(17,"mat-icon",9),t.ɵɵtext(18,"content_copy "),t.ɵɵelementEnd()()()()(),t.ɵɵelementStart(19,"section",1)(20,"mat-expansion-panel",10)(21,"mat-expansion-panel-header")(22,"mat-panel-title",11),t.ɵɵtext(23,"tb.rulenode.advanced-settings"),t.ɵɵelementEnd()(),t.ɵɵelementStart(24,"div",12),t.ɵɵpipe(25,"translate"),t.ɵɵelementStart(26,"mat-slide-toggle",13),t.ɵɵtext(27),t.ɵɵpipe(28,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(29,de,5,6,"div",14)(30,ue,5,6,"div",14),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.attributesConfigForm),t.ɵɵadvance(2),t.ɵɵproperty("hintText","tb.rulenode.attributes-scope-hint"),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(7,13,"tb.rulenode.attributes-scope")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.attributeScopes),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(13,15,"tb.rulenode.attributes-scope-value")),t.ɵɵadvance(2),t.ɵɵproperty("ngModel",n.attributesConfigForm.get("scope").value)("ngModelOptions",t.ɵɵpureFunction0(23,pe)),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(16,17,"tb.rulenode.attributes-scope-value-copy")),t.ɵɵproperty("cbContent",n.attributesConfigForm.get("scope").value),t.ɵɵadvance(9),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(25,19,n.attributesConfigForm.get("updateAttributesOnlyOnValueChange").value?"tb.rulenode.update-attributes-only-on-value-change-hint-enabled":"tb.rulenode.update-attributes-only-on-value-change-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(28,21,"tb.rulenode.update-attributes-only-on-value-change")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.attributesConfigForm.get("scope").value!==n.attributeScopeMap.CLIENT_SCOPE),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.attributesConfigForm.get("scope").value===n.attributeScopeMap.SHARED_SCOPE))},dependencies:t.ɵɵgetComponentDepsFactory(ce),encapsulation:2})}}e("AttributesConfigComponent",ce);const fe=["jsFuncComponent"],ge=["tbelFuncComponent"],he=()=>["msg","metadata","msgType"];function ye(e,n){1&e&&t.ɵɵelement(0,"tb-script-lang",12)}function be(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",13,0)(2,"button",14),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",15),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(4,he)),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,2,e.testScriptLabel))}}function ve(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",16,1)(2,"button",14),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",15),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(6,he))("disableUndefinedCheck",!0)("scriptLanguage",e.scriptLanguage.TBEL),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,4,e.testScriptLabel))}}function xe(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.alarm-type-required")," "))}class Ce extends i{constructor(e,t,r,a){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=r,this.translate=a,this.tbelEnabled=D(this.store).tbelEnabled,this.scriptLanguage=s,this.changeScript=new n,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:s.JS,[N.required]],alarmDetailsBuildJs:[e?e.alarmDetailsBuildJs:null,[]],alarmDetailsBuildTbel:[e?e.alarmDetailsBuildTbel:null,[]],alarmType:[e?e.alarmType:null,[N.required]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.clearAlarmConfigForm.get("scriptLang").value;t!==s.TBEL||this.tbelEnabled||(t=s.JS,this.clearAlarmConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.clearAlarmConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(t===s.JS?[N.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(t===s.TBEL?[N.required]:[]),this.clearAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=s.JS)),e}testScript(e){const t=this.clearAlarmConfigForm.get("scriptLang").value,n=t===s.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===s.JS?"rulenode/clear_alarm_node_script_fn":"rulenode/tbel/clear_alarm_node_script_fn",a=this.clearAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(a,"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===s.JS&&this.jsFuncComponent.validateOnSubmit()}static{this.ɵfac=function(e){return new(e||Ce)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder),t.ɵɵdirectiveInject(L.NodeScriptTestService),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Ce,selectors:[["tb-action-node-clear-alarm-config"]],viewQuery:function(e,n){if(1&e&&(t.ɵɵviewQuery(fe,5),t.ɵɵviewQuery(ge,5)),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.jsFuncComponent=e.first),t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.tbelFuncComponent=e.first)}},features:[t.ɵɵInheritDefinitionFeature],decls:15,vars:8,consts:[["jsFuncComponent",""],["tbelFuncComponent",""],[1,"flex","flex-col",3,"formGroup"],["formControlName","scriptLang",4,"ngIf"],["formControlName","alarmDetailsBuildJs","functionName","Details","helpId","rulenode/clear_alarm_node_script_fn","noValidate","true",3,"functionArgs",4,"ngIf"],["formControlName","alarmDetailsBuildTbel","functionName","Details","helpId","rulenode/tbel/clear_alarm_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage",4,"ngIf"],[1,"flex","flex-row",2,"padding-bottom","16px"],["mat-button","","mat-raised-button","","color","primary",3,"click"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","alarmType"],[4,"ngIf"],["formControlName","scriptLang"],["formControlName","alarmDetailsBuildJs","functionName","Details","helpId","rulenode/clear_alarm_node_script_fn","noValidate","true",3,"functionArgs"],["toolbarSuffixButton","","mat-icon-button","","matTooltipPosition","above",1,"tb-mat-32",3,"click","matTooltip"],["color","primary",1,"material-icons"],["formControlName","alarmDetailsBuildTbel","functionName","Details","helpId","rulenode/tbel/clear_alarm_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",2),t.ɵɵtemplate(1,ye,1,0,"tb-script-lang",3)(2,be,6,5,"tb-js-func",4)(3,ve,6,7,"tb-js-func",5),t.ɵɵelementStart(4,"div",6)(5,"button",7),t.ɵɵlistener("click",(function(){return n.testScript()})),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(8,"mat-form-field",8)(9,"mat-label",9),t.ɵɵtext(10,"tb.rulenode.alarm-type"),t.ɵɵelementEnd(),t.ɵɵelement(11,"input",10),t.ɵɵtemplate(12,xe,3,3,"mat-error",11),t.ɵɵelementStart(13,"mat-hint",9),t.ɵɵtext(14,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.clearAlarmConfigForm),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.tbelEnabled),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.clearAlarmConfigForm.get("scriptLang").value===n.scriptLanguage.JS),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.clearAlarmConfigForm.get("scriptLang").value===n.scriptLanguage.TBEL),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(7,6,n.testScriptLabel)," "),t.ɵɵadvance(6),t.ɵɵproperty("ngIf",n.clearAlarmConfigForm.get("alarmType").hasError("required")))},dependencies:t.ɵɵgetComponentDepsFactory(Ce),encapsulation:2})}}e("ClearAlarmConfigComponent",Ce);const Se=["jsFuncComponent"],Te=["tbelFuncComponent"],Ie=()=>["msg","metadata","msgType"];function Ee(e,n){1&e&&(t.ɵɵelementStart(0,"mat-checkbox",7),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.overwrite-alarm-details")," "))}function Fe(e,n){1&e&&t.ɵɵelement(0,"tb-script-lang",14)}function qe(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",15,0)(2,"button",16),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext(2);return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",17),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext(2);t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(4,Ie)),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,2,e.testScriptLabel))}}function Ae(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",18,1)(2,"button",16),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext(2);return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",17),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext(2);t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(6,Ie))("disableUndefinedCheck",!0)("scriptLanguage",e.scriptLanguage.TBEL),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,4,e.testScriptLabel))}}function ke(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"section",8),t.ɵɵtemplate(1,Fe,1,0,"tb-script-lang",9)(2,qe,6,5,"tb-js-func",10)(3,Ae,6,7,"tb-js-func",11),t.ɵɵelementStart(4,"div",12)(5,"button",13),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.tbelEnabled),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.createAlarmConfigForm.get("scriptLang").value===e.scriptLanguage.JS),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.createAlarmConfigForm.get("scriptLang").value===e.scriptLanguage.TBEL),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(7,4,e.testScriptLabel)," ")}}function Ne(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.alarm-type-required")," "))}function we(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",32),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(3);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.alarmSeverityTranslationMap.get(e))," ")}}function Me(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.alarm-severity-required")," "))}function Be(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",29)(1,"mat-label",20),t.ɵɵtext(2,"tb.rulenode.alarm-severity"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"mat-select",30),t.ɵɵtemplate(4,we,3,4,"mat-option",31),t.ɵɵelementEnd(),t.ɵɵtemplate(5,Me,3,3,"mat-error",22),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(4),t.ɵɵproperty("ngForOf",e.alarmSeverities),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.createAlarmConfigForm.get("severity").hasError("required"))}}function Ve(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.alarm-severity-required")," "))}function Oe(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",19)(1,"mat-label",20),t.ɵɵtext(2,"tb.rulenode.alarm-severity-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",33),t.ɵɵtemplate(4,Ve,3,3,"mat-error",22),t.ɵɵelement(5,"mat-hint",34),t.ɵɵpipe(6,"translate"),t.ɵɵpipe(7,"safe"),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(4),t.ɵɵproperty("ngIf",e.createAlarmConfigForm.get("severity").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(7,4,t.ɵɵpipeBind1(6,2,"tb.rulenode.alarm-severity-pattern-hint"),"html"),t.ɵɵsanitizeHtml)}}function De(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"mat-chip-row",38),t.ɵɵlistener("removed",(function(){const n=t.ɵɵrestoreView(e).$implicit,r=t.ɵɵnextContext(3);return t.ɵɵresetView(r.removeKey(n,"relationTypes"))})),t.ɵɵtext(1),t.ɵɵelementStart(2,"mat-icon",39),t.ɵɵtext(3,"close"),t.ɵɵelementEnd()()}if(2&e){const e=n.$implicit;t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e," ")}}function Le(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"section")(1,"mat-form-field",35)(2,"mat-label",20),t.ɵɵtext(3,"tb.rulenode.relation-types-list"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"mat-chip-grid",null,2),t.ɵɵtemplate(6,De,4,1,"mat-chip-row",36),t.ɵɵelementStart(7,"input",37),t.ɵɵpipe(8,"translate"),t.ɵɵlistener("matChipInputTokenEnd",(function(n){t.ɵɵrestoreView(e);const r=t.ɵɵnextContext(2);return t.ɵɵresetView(r.addKey(n,"relationTypes"))})),t.ɵɵelementEnd()(),t.ɵɵelementStart(9,"mat-hint",20),t.ɵɵtext(10,"tb.rulenode.relation-types-list-hint"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵreference(5),n=t.ɵɵnextContext(2);t.ɵɵadvance(6),t.ɵɵproperty("ngForOf",n.createAlarmConfigForm.get("relationTypes").value),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("placeholder",t.ɵɵpipeBind1(8,5,"tb.rulenode.relation-types-list")),t.ɵɵproperty("matChipInputFor",e)("matChipInputSeparatorKeyCodes",n.separatorKeysCodes)("matChipInputAddOnBlur",!0)}}function Pe(e,n){if(1&e&&(t.ɵɵelementStart(0,"section",8)(1,"mat-form-field",19)(2,"mat-label",20),t.ɵɵtext(3,"tb.rulenode.alarm-type"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",21),t.ɵɵtemplate(5,Ne,3,3,"mat-error",22),t.ɵɵelementStart(6,"mat-hint",20),t.ɵɵtext(7,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(8,"mat-checkbox",23),t.ɵɵtext(9),t.ɵɵpipe(10,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(11,Be,6,2,"mat-form-field",24)(12,Oe,8,7,"mat-form-field",25),t.ɵɵelementStart(13,"mat-checkbox",26),t.ɵɵtext(14),t.ɵɵpipe(15,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(16,Le,11,7,"section",22),t.ɵɵelementStart(17,"mat-checkbox",27),t.ɵɵtext(18),t.ɵɵpipe(19,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(20,"mat-checkbox",28),t.ɵɵtext(21),t.ɵɵpipe(22,"translate"),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(5),t.ɵɵproperty("ngIf",e.createAlarmConfigForm.get("alarmType").hasError("required")),t.ɵɵadvance(4),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(10,8,"tb.rulenode.use-alarm-severity-pattern")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!e.createAlarmConfigForm.get("dynamicSeverity").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.createAlarmConfigForm.get("dynamicSeverity").value),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(15,10,"tb.rulenode.propagate")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!0===e.createAlarmConfigForm.get("propagate").value),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(19,12,"tb.rulenode.propagate-to-owner")," "),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(22,14,"tb.rulenode.propagate-to-tenant")," ")}}class Re extends i{constructor(e,t,r,a){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=r,this.translate=a,this.alarmSeverities=Object.keys(p),this.alarmSeverityTranslationMap=m,this.separatorKeysCodes=[U,H,z],this.tbelEnabled=D(this.store).tbelEnabled,this.scriptLanguage=s,this.changeScript=new n,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:s.JS,[N.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([N.required]),this.createAlarmConfigForm.get("severity").setValidators([N.required])),this.createAlarmConfigForm.get("alarmType").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("severity").updateValueAndValidity({emitEvent:e});let r=this.createAlarmConfigForm.get("scriptLang").value;r!==s.TBEL||this.tbelEnabled||(r=s.JS,this.createAlarmConfigForm.get("scriptLang").patchValue(r,{emitEvent:!1}),setTimeout((()=>{this.createAlarmConfigForm.updateValueAndValidity({emitEvent:!0})})));const a=!1===t||!0===n;this.createAlarmConfigForm.get("alarmDetailsBuildJs").setValidators(a&&r===s.JS?[N.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").setValidators(a&&r===s.TBEL?[N.required]:[]),this.createAlarmConfigForm.get("alarmDetailsBuildJs").updateValueAndValidity({emitEvent:e}),this.createAlarmConfigForm.get("alarmDetailsBuildTbel").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=s.JS)),e}testScript(e){const t=this.createAlarmConfigForm.get("scriptLang").value,n=t===s.JS?"alarmDetailsBuildJs":"alarmDetailsBuildTbel",r=t===s.JS?"rulenode/create_alarm_node_script_fn":"rulenode/tbel/create_alarm_node_script_fn",a=this.createAlarmConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(a,"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===s.JS&&this.jsFuncComponent.validateOnSubmit()}}static{this.ɵfac=function(e){return new(e||Re)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder),t.ɵɵdirectiveInject(L.NodeScriptTestService),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Re,selectors:[["tb-action-node-create-alarm-config"]],viewQuery:function(e,n){if(1&e&&(t.ɵɵviewQuery(Se,5),t.ɵɵviewQuery(Te,5)),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.jsFuncComponent=e.first),t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.tbelFuncComponent=e.first)}},features:[t.ɵɵInheritDefinitionFeature],decls:7,vars:7,consts:[["jsFuncComponent",""],["tbelFuncComponent",""],["relationTypesChipList",""],[1,"flex","flex-col",3,"formGroup"],["formControlName","useMessageAlarmData"],["formControlName","overwriteAlarmDetails",4,"ngIf"],["class","flex flex-col",4,"ngIf"],["formControlName","overwriteAlarmDetails"],[1,"flex","flex-col"],["formControlName","scriptLang",4,"ngIf"],["formControlName","alarmDetailsBuildJs","functionName","Details","helpId","rulenode/create_alarm_node_script_fn","noValidate","true",3,"functionArgs",4,"ngIf"],["formControlName","alarmDetailsBuildTbel","functionName","Details","helpId","rulenode/tbel/create_alarm_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage",4,"ngIf"],[1,"flex","flex-row",2,"padding-bottom","16px"],["mat-button","","mat-raised-button","","color","primary",3,"click"],["formControlName","scriptLang"],["formControlName","alarmDetailsBuildJs","functionName","Details","helpId","rulenode/create_alarm_node_script_fn","noValidate","true",3,"functionArgs"],["toolbarSuffixButton","","mat-icon-button","","matTooltipPosition","above",1,"tb-mat-32",3,"click","matTooltip"],["color","primary",1,"material-icons"],["formControlName","alarmDetailsBuildTbel","functionName","Details","helpId","rulenode/tbel/create_alarm_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage"],["subscriptSizing","dynamic",1,"flex-1"],["translate",""],["required","","matInput","","formControlName","alarmType"],[4,"ngIf"],["formControlName","dynamicSeverity"],["class","flex-1",4,"ngIf"],["class","flex-1","subscriptSizing","dynamic",4,"ngIf"],["formControlName","propagate"],["formControlName","propagateToOwner"],["formControlName","propagateToTenant"],[1,"flex-1"],["formControlName","severity","required",""],[3,"value",4,"ngFor","ngForOf"],[3,"value"],["matInput","","formControlName","severity","required",""],[3,"innerHTML"],["floatLabel","always","subscriptSizing","dynamic",1,"mat-block"],[3,"removed",4,"ngFor","ngForOf"],["matInput","","type","text",3,"matChipInputTokenEnd","placeholder","matChipInputFor","matChipInputSeparatorKeyCodes","matChipInputAddOnBlur"],[3,"removed"],["matChipRemove",""]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",3)(1,"mat-checkbox",4),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(4,Ee,3,3,"mat-checkbox",5)(5,ke,8,6,"section",6)(6,Pe,23,16,"section",6),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.createAlarmConfigForm),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(3,5,"tb.rulenode.use-message-alarm-data")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!0===n.createAlarmConfigForm.get("useMessageAlarmData").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",!1===n.createAlarmConfigForm.get("useMessageAlarmData").value||!0===n.createAlarmConfigForm.get("overwriteAlarmDetails").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",!1===n.createAlarmConfigForm.get("useMessageAlarmData").value))},dependencies:t.ɵɵgetComponentDepsFactory(Re),encapsulation:2})}}function _e(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",21),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.directionTypeTranslations.get(e))," ")}}function je(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",22)(1,"mat-label"),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",23),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(3,1,e.entityTypeNamePatternTranslation.get(e.createRelationConfigForm.get("entityType").value)))}}function Ge(e,n){1&e&&(t.ɵɵelementStart(0,"mat-form-field",22)(1,"mat-label",5),t.ɵɵtext(2,"tb.rulenode.profile-name"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",24),t.ɵɵelementEnd())}function Ke(e,n){1&e&&t.ɵɵelement(0,"tb-example-hint",25),2&e&&t.ɵɵproperty("hintText","tb.rulenode.kv-map-pattern-hint")}function Ue(e,n){1&e&&(t.ɵɵelementStart(0,"div",26),t.ɵɵpipe(1,"translate"),t.ɵɵelementStart(2,"mat-slide-toggle",27),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(1,2,"tb.rulenode.create-entity-if-not-exists-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(4,4,"tb.rulenode.create-entity-if-not-exists")," "))}e("CreateAlarmConfigComponent",Re);class He extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(d),this.directionTypeTranslations=new Map([[d.FROM,"tb.rulenode.search-direction-from"],[d.TO,"tb.rulenode.search-direction-to"]]),this.entityType=u,this.entityTypeNamePatternTranslation=new Map([[u.DEVICE,"tb.rulenode.device-name-pattern"],[u.ASSET,"tb.rulenode.asset-name-pattern"],[u.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[u.CUSTOMER,"tb.rulenode.customer-title-pattern"],[u.USER,"tb.rulenode.user-name-pattern"],[u.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[u.EDGE,"tb.rulenode.edge-name-pattern"]]),this.allowedEntityTypes=[u.DEVICE,u.ASSET,u.ENTITY_VIEW,u.TENANT,u.CUSTOMER,u.USER,u.DASHBOARD,u.EDGE]}configForm(){return this.createRelationConfigForm}onConfigurationSet(e){this.createRelationConfigForm=this.fb.group({direction:[e?e.direction:null,[N.required]],entityType:[e?e.entityType:null,[N.required]],entityNamePattern:[e?e.entityNamePattern:null,[]],entityTypePattern:[e?e.entityTypePattern:null,[]],relationType:[e?e.relationType:null,[N.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([N.required,N.pattern(/.*\S.*/)]):this.createRelationConfigForm.get("entityNamePattern").setValidators([]),!t||t!==u.DEVICE&&t!==u.ASSET)this.createRelationConfigForm.get("entityTypePattern").setValidators([]);else{const e=[N.pattern(/.*\S.*/)];this.createRelationConfigForm.get("createEntityIfNotExists").value&&e.push(N.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}static{this.ɵfac=function(e){return new(e||He)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:He,selectors:[["tb-action-node-create-relation-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:36,vars:19,consts:[[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],[1,"tb-form-panel","stroked","no-padding-bottom"],["translate","",1,"tb-form-panel-title"],[1,"flex","flex-col"],["hideRequiredMarker","",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","direction"],[3,"value",4,"ngFor","ngForOf"],["required","","formControlName","relationType"],[1,"flex","flex-row","gap-4"],["showLabel","","required","","formControlName","entityType",1,"flex-1",3,"allowedEntityTypes"],["class","mat-block flex-1",4,"ngIf"],[3,"hintText",4,"ngIf"],["style","margin-bottom: 18px","class","tb-form-row no-border no-padding",3,"tb-hint-tooltip-icon",4,"ngIf"],[1,"tb-form-panel","stroked","no-padding"],[1,"tb-settings"],[2,"padding","16px"],[1,"tb-form-panel","no-border","no-padding-top"],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","removeCurrentRelations",1,"mat-slide"],["formControlName","changeOriginatorToRelatedEntity",1,"mat-slide"],[3,"value"],[1,"mat-block","flex-1"],["required","","matInput","","formControlName","entityNamePattern"],["matInput","","formControlName","entityTypePattern"],[3,"hintText"],[1,"tb-form-row","no-border","no-padding",2,"margin-bottom","18px",3,"tb-hint-tooltip-icon"],["formControlName","createEntityIfNotExists",1,"mat-slide"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2),t.ɵɵtext(3,"tb.rulenode.relation-parameters"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"div",3)(5,"mat-form-field",4)(6,"mat-label",5),t.ɵɵtext(7,"relation.direction"),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-select",6),t.ɵɵtemplate(9,_e,3,4,"mat-option",7),t.ɵɵelementEnd()(),t.ɵɵelement(10,"tb-relation-type-autocomplete",8),t.ɵɵelementEnd()(),t.ɵɵelementStart(11,"div",1)(12,"div",2),t.ɵɵtext(13,"tb.rulenode.target-entity"),t.ɵɵelementEnd(),t.ɵɵelementStart(14,"div",9),t.ɵɵelement(15,"tb-entity-type-select",10),t.ɵɵtemplate(16,je,5,3,"mat-form-field",11)(17,Ge,4,0,"mat-form-field",11),t.ɵɵelementEnd(),t.ɵɵtemplate(18,Ke,1,1,"tb-example-hint",12)(19,Ue,5,6,"div",13),t.ɵɵelementEnd(),t.ɵɵelementStart(20,"section",14)(21,"mat-expansion-panel",15)(22,"mat-expansion-panel-header",16)(23,"mat-panel-title",5),t.ɵɵtext(24,"tb.rulenode.advanced-settings"),t.ɵɵelementEnd()(),t.ɵɵelementStart(25,"div",17)(26,"div",18),t.ɵɵpipe(27,"translate"),t.ɵɵelementStart(28,"mat-slide-toggle",19),t.ɵɵtext(29),t.ɵɵpipe(30,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(31,"div",18),t.ɵɵpipe(32,"translate"),t.ɵɵelementStart(33,"mat-slide-toggle",20),t.ɵɵtext(34),t.ɵɵpipe(35,"translate"),t.ɵɵelementEnd()()()()()()),2&e&&(t.ɵɵproperty("formGroup",n.createRelationConfigForm),t.ɵɵadvance(9),t.ɵɵproperty("ngForOf",n.directionTypes),t.ɵɵadvance(6),t.ɵɵproperty("allowedEntityTypes",n.allowedEntityTypes),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.createRelationConfigForm.get("entityType").value&&n.createRelationConfigForm.get("entityType").value!==n.entityType.TENANT),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.createRelationConfigForm.get("entityType").value===n.entityType.DEVICE||n.createRelationConfigForm.get("entityType").value===n.entityType.ASSET),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.createRelationConfigForm.get("entityType").value===n.entityType.CUSTOMER||n.createRelationConfigForm.get("entityType").value===n.entityType.DEVICE||n.createRelationConfigForm.get("entityType").value===n.entityType.ASSET),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.createRelationConfigForm.get("entityType").value===n.entityType.CUSTOMER||n.createRelationConfigForm.get("entityType").value===n.entityType.DEVICE||n.createRelationConfigForm.get("entityType").value===n.entityType.ASSET),t.ɵɵadvance(7),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(27,11,"tb.rulenode.remove-current-relations-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(30,13,"tb.rulenode.remove-current-relations")," "),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(32,15,"tb.rulenode.change-originator-to-related-entity-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(35,17,"tb.rulenode.change-originator-to-related-entity")," "))},dependencies:t.ɵɵgetComponentDepsFactory(He),encapsulation:2})}}function ze(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",13),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.directionTypeTranslations.get(e))," ")}}function $e(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",18)(1,"mat-label"),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",19),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(3,1,e.entityTypeNamePatternTranslation.get(e.deleteRelationConfigForm.get("entityType").value)))}}function Qe(e,n){1&e&&t.ɵɵelement(0,"tb-example-hint",20),2&e&&t.ɵɵproperty("hintText","tb.rulenode.kv-map-single-pattern-hint")}function Je(e,n){if(1&e&&(t.ɵɵelementStart(0,"div")(1,"div",14),t.ɵɵelement(2,"tb-entity-type-select",15),t.ɵɵtemplate(3,$e,5,3,"mat-form-field",16),t.ɵɵelementEnd(),t.ɵɵtemplate(4,Qe,1,1,"tb-example-hint",17),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵproperty("allowedEntityTypes",e.allowedEntityTypes),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.deleteRelationConfigForm.get("entityType").value&&e.deleteRelationConfigForm.get("entityType").value!==e.entityType.TENANT),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.deleteRelationConfigForm.get("entityType").value&&e.deleteRelationConfigForm.get("entityType").value!==e.entityType.TENANT)}}e("CreateRelationConfigComponent",He);class Ye extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(d),this.directionTypeTranslations=new Map([[d.FROM,"tb.rulenode.del-relation-direction-from"],[d.TO,"tb.rulenode.del-relation-direction-to"]]),this.entityTypeNamePatternTranslation=new Map([[u.DEVICE,"tb.rulenode.device-name-pattern"],[u.ASSET,"tb.rulenode.asset-name-pattern"],[u.ENTITY_VIEW,"tb.rulenode.entity-view-name-pattern"],[u.CUSTOMER,"tb.rulenode.customer-title-pattern"],[u.USER,"tb.rulenode.user-name-pattern"],[u.DASHBOARD,"tb.rulenode.dashboard-name-pattern"],[u.EDGE,"tb.rulenode.edge-name-pattern"]]),this.entityType=u,this.allowedEntityTypes=[u.DEVICE,u.ASSET,u.ENTITY_VIEW,u.TENANT,u.CUSTOMER,u.USER,u.DASHBOARD,u.EDGE]}configForm(){return this.deleteRelationConfigForm}onConfigurationSet(e){this.deleteRelationConfigForm=this.fb.group({deleteForSingleEntity:[!!e&&e.deleteForSingleEntity,[]],direction:[e?e.direction:null,[N.required]],entityType:[e?e.entityType:null,[]],entityNamePattern:[e?e.entityNamePattern:null,[]],relationType:[e?e.relationType:null,[N.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([N.required]):this.deleteRelationConfigForm.get("entityType").setValidators([]),t&&n&&n!==u.TENANT?this.deleteRelationConfigForm.get("entityNamePattern").setValidators([N.required,N.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}static{this.ɵfac=function(e){return new(e||Ye)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Ye,selectors:[["tb-action-node-delete-relation-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:18,vars:9,consts:[[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],[1,"tb-form-panel","stroked","no-padding-bottom"],["translate","",1,"tb-form-panel-title"],[1,"flex","flex-col"],["hideRequiredMarker","",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","direction"],[3,"value",4,"ngFor","ngForOf"],["required","","formControlName","relationType"],[1,"tb-form-panel","stroked"],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","deleteForSingleEntity",1,"mat-slide"],[4,"ngIf"],[3,"value"],[1,"flex","flex-row","gap-2.5"],["showLabel","","required","","formControlName","entityType",1,"flex-1",3,"allowedEntityTypes"],["class","mat-block flex-1",4,"ngIf"],[3,"hintText",4,"ngIf"],[1,"mat-block","flex-1"],["required","","matInput","","formControlName","entityNamePattern"],[3,"hintText"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2),t.ɵɵtext(3,"tb.rulenode.relation-parameters"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"div",3)(5,"mat-form-field",4)(6,"mat-label",5),t.ɵɵtext(7,"relation.direction"),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-select",6),t.ɵɵtemplate(9,ze,3,4,"mat-option",7),t.ɵɵelementEnd()(),t.ɵɵelement(10,"tb-relation-type-autocomplete",8),t.ɵɵelementEnd()(),t.ɵɵelementStart(11,"div",9)(12,"div",10),t.ɵɵpipe(13,"translate"),t.ɵɵelementStart(14,"mat-slide-toggle",11),t.ɵɵtext(15),t.ɵɵpipe(16,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(17,Je,5,3,"div",12),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.deleteRelationConfigForm),t.ɵɵadvance(9),t.ɵɵproperty("ngForOf",n.directionTypes),t.ɵɵadvance(3),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(13,5,"tb.rulenode.delete-relation-with-specific-entity-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(16,7,"tb.rulenode.delete-relation-with-specific-entity")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.deleteRelationConfigForm.get("deleteForSingleEntity").value))},dependencies:t.ɵɵgetComponentDepsFactory(Ye),encapsulation:2})}}e("DeleteRelationConfigComponent",Ye);class We extends i{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})}static{this.ɵfac=function(e){return new(e||We)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:We,selectors:[["tb-device-profile-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:13,vars:13,consts:[[1,"tb-form-panel","stroked",3,"formGroup"],["translate","",1,"tb-form-hint","tb-primary-fill"],[1,"tb-form-row","no-border","no-padding","slide-toggle",3,"tb-hint-tooltip-icon"],["formControlName","persistAlarmRulesState",1,"mat-slide"],["formControlName","fetchAlarmRulesStateOnStart",1,"mat-slide"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵtext(2,"tb.rulenode.device-profile-node-hint"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"div",2),t.ɵɵpipe(4,"translate"),t.ɵɵelementStart(5,"mat-slide-toggle",3),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(8,"div",2),t.ɵɵpipe(9,"translate"),t.ɵɵelementStart(10,"mat-slide-toggle",4),t.ɵɵtext(11),t.ɵɵpipe(12,"translate"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.deviceProfile),t.ɵɵadvance(3),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(4,5,"tb.rulenode.persist-alarm-rules-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(7,7,"tb.rulenode.persist-alarm-rules")," "),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(9,9,"tb.rulenode.fetch-alarm-rules-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(12,11,"tb.rulenode.fetch-alarm-rules")," "))},dependencies:t.ɵɵgetComponentDepsFactory(We),encapsulation:2})}}e("DeviceProfileConfigComponent",We);const Xe=["jsFuncComponent"],Ze=["tbelFuncComponent"],et=()=>["prevMsg","prevMetadata","prevMsgType"];function tt(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.message-count-required")," "))}function nt(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-message-count-message")," "))}function rt(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.generation-frequency-required")," "))}function at(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-generation-frequency-message")," "))}function it(e,n){if(1&e&&(t.ɵɵelementStart(0,"tb-toggle-select",22)(1,"tb-toggle-option",23),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"tb-toggle-option",23),t.ɵɵtext(5),t.ɵɵpipe(6,"translate"),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(),t.ɵɵproperty("value",e.scriptLanguage.TBEL),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(3,4,"tb.rulenode.script-lang-tbel")," "),t.ɵɵadvance(2),t.ɵɵproperty("value",e.scriptLanguage.JS),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(6,6,"tb.rulenode.script-lang-js")," ")}}function ot(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",18,0),t.ɵɵtemplate(2,it,7,8,"tb-toggle-select",19),t.ɵɵelementStart(3,"button",20),t.ɵɵpipe(4,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(5,"mat-icon",21),t.ɵɵtext(6,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(5,et)),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",e.tbelEnabled),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(4,3,e.testScriptLabel))}}function lt(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",24,1)(2,"tb-toggle-select",22)(3,"tb-toggle-option",23),t.ɵɵtext(4),t.ɵɵpipe(5,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(6,"tb-toggle-option",23),t.ɵɵtext(7),t.ɵɵpipe(8,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(9,"button",20),t.ɵɵpipe(10,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(11,"mat-icon",21),t.ɵɵtext(12,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(14,et))("disableUndefinedCheck",!0)("scriptLanguage",e.scriptLanguage.TBEL),t.ɵɵadvance(3),t.ɵɵproperty("value",e.scriptLanguage.TBEL),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(5,8,"tb.rulenode.script-lang-tbel")," "),t.ɵɵadvance(2),t.ɵɵproperty("value",e.scriptLanguage.JS),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(8,10,"tb.rulenode.script-lang-js")," "),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(10,12,e.testScriptLabel))}}class st extends i{constructor(e,t,r,a){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=r,this.translate=a,this.tbelEnabled=D(this.store).tbelEnabled,this.scriptLanguage=s,this.changeScript=new n,this.allowedEntityTypes=[u.DEVICE,u.ASSET,u.ENTITY_VIEW,u.CUSTOMER,u.USER,u.DASHBOARD],this.additionEntityTypes={TENANT:this.translate.instant("tb.rulenode.current-tenant"),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,[N.required,N.min(0)]],periodInSeconds:[e?e.periodInSeconds:null,[N.required,N.min(1)]],originator:[e?e.originator:{id:null,entityType:u.RULE_NODE},[]],scriptLang:[e?e.scriptLang:s.JS,[N.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.generatorConfigForm.get("scriptLang").value;t!==s.TBEL||this.tbelEnabled||(t=s.JS,this.generatorConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.generatorConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.generatorConfigForm.get("jsScript").setValidators(t===s.JS?[N.required]:[]),this.generatorConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.generatorConfigForm.get("tbelScript").setValidators(t===s.TBEL?[N.required]:[]),this.generatorConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return{msgCount:P(e?.msgCount)?e?.msgCount:0,periodInSeconds:P(e?.periodInSeconds)?e?.periodInSeconds:1,originator:{id:P(e?.originatorId)?e?.originatorId:null,entityType:P(e?.originatorType)?e?.originatorType:u.RULE_NODE},scriptLang:P(e?.scriptLang)?e?.scriptLang:s.JS,tbelScript:P(e?.tbelScript)?e?.tbelScript:null,jsScript:P(e?.jsScript)?e?.jsScript:null}}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===s.JS?"jsScript":"tbelScript",r=t===s.JS?"rulenode/generator_node_script_fn":"rulenode/tbel/generator_node_script_fn",a=this.generatorConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(a,"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===s.JS&&this.jsFuncComponent.validateOnSubmit()}static{this.ɵfac=function(e){return new(e||st)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder),t.ɵɵdirectiveInject(L.NodeScriptTestService),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:st,selectors:[["tb-action-node-generator-config"]],viewQuery:function(e,n){if(1&e&&(t.ɵɵviewQuery(Xe,5),t.ɵɵviewQuery(Ze,5)),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.jsFuncComponent=e.first),t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.tbelFuncComponent=e.first)}},features:[t.ɵɵInheritDefinitionFeature],decls:32,vars:12,consts:[["jsFuncComponent",""],["tbelFuncComponent",""],[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],[1,"tb-form-panel","no-padding-bottom","stroked"],["translate","",1,"tb-form-panel-title"],[1,"tb-form-row","no-border","no-padding","tb-standard-fields","column-xs"],[1,"flex"],["translate",""],["required","","type","number","min","0","step","1","matInput","","formControlName","msgCount"],[4,"ngIf"],["required","","type","number","min","1","step","1","matInput","","formControlName","periodInSeconds"],["required","true","useAliasEntityTypes","true","formControlName","originator",1,"flex-1",3,"allowedEntityTypes","additionEntityTypes"],[1,"tb-form-panel","stroked"],["expanded","",1,"tb-settings"],["formControlName","jsScript","functionName","Generate","helpId","rulenode/generator_node_script_fn","noValidate","true",3,"functionArgs",4,"ngIf"],["formControlName","tbelScript","functionName","Generate","helpId","rulenode/tbel/generator_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage",4,"ngIf"],[1,"flex","flex-row",2,"padding-bottom","16px"],["mat-button","","mat-raised-button","","color","primary",3,"click"],["formControlName","jsScript","functionName","Generate","helpId","rulenode/generator_node_script_fn","noValidate","true",3,"functionArgs"],["toolbarPrefixButton","","formControlName","scriptLang","appearance","fill",4,"ngIf"],["toolbarSuffixButton","","mat-icon-button","","matTooltipPosition","above",1,"tb-mat-32",3,"click","matTooltip"],["color","primary",1,"material-icons"],["toolbarPrefixButton","","formControlName","scriptLang","appearance","fill"],[3,"value"],["formControlName","tbelScript","functionName","Generate","helpId","rulenode/tbel/generator_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",2)(1,"div",3)(2,"div",4),t.ɵɵtext(3,"tb.rulenode.generation-parameters"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"div",5)(5,"mat-form-field",6)(6,"mat-label",7),t.ɵɵtext(7,"tb.rulenode.message-count"),t.ɵɵelementEnd(),t.ɵɵelement(8,"input",8),t.ɵɵtemplate(9,tt,3,3,"mat-error",9)(10,nt,3,3,"mat-error",9),t.ɵɵelementEnd(),t.ɵɵelementStart(11,"mat-form-field",6)(12,"mat-label",7),t.ɵɵtext(13,"tb.rulenode.generation-frequency-seconds"),t.ɵɵelementEnd(),t.ɵɵelement(14,"input",10),t.ɵɵtemplate(15,rt,3,3,"mat-error",9)(16,at,3,3,"mat-error",9),t.ɵɵelementEnd()()(),t.ɵɵelementStart(17,"div",3)(18,"div",4),t.ɵɵtext(19,"tb.rulenode.originator"),t.ɵɵelementEnd(),t.ɵɵelement(20,"tb-entity-select",11),t.ɵɵelementEnd(),t.ɵɵelementStart(21,"div",12)(22,"mat-expansion-panel",13)(23,"mat-expansion-panel-header")(24,"mat-panel-title",7),t.ɵɵtext(25,"tb.rulenode.generator-function"),t.ɵɵelementEnd()(),t.ɵɵtemplate(26,ot,7,6,"tb-js-func",14)(27,lt,13,15,"tb-js-func",15),t.ɵɵelementStart(28,"div",16)(29,"button",17),t.ɵɵlistener("click",(function(){return n.testScript()})),t.ɵɵtext(30),t.ɵɵpipe(31,"translate"),t.ɵɵelementEnd()()()()()),2&e&&(t.ɵɵproperty("formGroup",n.generatorConfigForm),t.ɵɵadvance(9),t.ɵɵproperty("ngIf",n.generatorConfigForm.get("msgCount").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.generatorConfigForm.get("msgCount").hasError("min")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.generatorConfigForm.get("periodInSeconds").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.generatorConfigForm.get("periodInSeconds").hasError("min")),t.ɵɵadvance(4),t.ɵɵproperty("allowedEntityTypes",n.allowedEntityTypes)("additionEntityTypes",n.additionEntityTypes),t.ɵɵadvance(6),t.ɵɵproperty("ngIf",n.generatorConfigForm.get("scriptLang").value===n.scriptLanguage.JS),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.generatorConfigForm.get("scriptLang").value===n.scriptLanguage.TBEL),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(31,10,n.testScriptLabel)," "))},dependencies:t.ɵɵgetComponentDepsFactory(st),styles:["[_nghost-%COMP%] .mat-button-toggle-group{min-width:120px;height:24px!important}[_nghost-%COMP%] .mat-button-toggle-group .mat-button-toggle{font-size:0}[_nghost-%COMP%] .mat-button-toggle-group .mat-button-toggle .mat-button-toggle-button{height:20px!important;line-height:20px!important;border:none!important}[_nghost-%COMP%] .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){[_nghost-%COMP%] .tb-entity-select{display:flex;flex-direction:row;gap:16px}}[_nghost-%COMP%] .tb-entity-select tb-entity-type-select{flex:1}[_nghost-%COMP%] .tb-entity-select tb-entity-autocomplete{flex:1}[_nghost-%COMP%] .tb-entity-select tb-entity-autocomplete mat-form-field{width:100%!important}"]})}}var pt;e("GeneratorConfigComponent",st),function(e){e.CUSTOMER="CUSTOMER",e.TENANT="TENANT",e.RELATED="RELATED",e.ALARM_ORIGINATOR="ALARM_ORIGINATOR",e.ENTITY="ENTITY"}(pt||(pt={}));const mt=new Map([[pt.CUSTOMER,"tb.rulenode.originator-customer"],[pt.TENANT,"tb.rulenode.originator-tenant"],[pt.RELATED,"tb.rulenode.originator-related"],[pt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator"],[pt.ENTITY,"tb.rulenode.originator-entity"]]),dt=new Map([[pt.CUSTOMER,"tb.rulenode.originator-customer-desc"],[pt.TENANT,"tb.rulenode.originator-tenant-desc"],[pt.RELATED,"tb.rulenode.originator-related-entity-desc"],[pt.ALARM_ORIGINATOR,"tb.rulenode.originator-alarm-originator-desc"],[pt.ENTITY,"tb.rulenode.originator-entity-by-name-pattern-desc"]]),ut=[c.createdTime,c.name,{value:"type",name:"tb.rulenode.profile-name",keyName:"originatorProfileName"},c.firstName,c.lastName,c.email,c.title,c.country,c.state,c.city,c.address,c.address2,c.zip,c.phone,c.label,{value:"id",name:"tb.rulenode.id",keyName:"id"},{value:"additionalInfo",name:"tb.rulenode.additional-info",keyName:"additionalInfo"}],ct=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 ft;!function(e){e.CIRCLE="CIRCLE",e.POLYGON="POLYGON"}(ft||(ft={}));const gt=new Map([[ft.CIRCLE,"tb.rulenode.perimeter-circle"],[ft.POLYGON,"tb.rulenode.perimeter-polygon"]]);var ht;!function(e){e.MILLISECONDS="MILLISECONDS",e.SECONDS="SECONDS",e.MINUTES="MINUTES",e.HOURS="HOURS",e.DAYS="DAYS"}(ht||(ht={}));const yt=new Map([[ht.MILLISECONDS,"tb.rulenode.time-unit-milliseconds"],[ht.SECONDS,"tb.rulenode.time-unit-seconds"],[ht.MINUTES,"tb.rulenode.time-unit-minutes"],[ht.HOURS,"tb.rulenode.time-unit-hours"],[ht.DAYS,"tb.rulenode.time-unit-days"]]);var bt;!function(e){e.METER="METER",e.KILOMETER="KILOMETER",e.FOOT="FOOT",e.MILE="MILE",e.NAUTICAL_MILE="NAUTICAL_MILE"}(bt||(bt={}));const vt=new Map([[bt.METER,"tb.rulenode.range-unit-meter"],[bt.KILOMETER,"tb.rulenode.range-unit-kilometer"],[bt.FOOT,"tb.rulenode.range-unit-foot"],[bt.MILE,"tb.rulenode.range-unit-mile"],[bt.NAUTICAL_MILE,"tb.rulenode.range-unit-nautical-mile"]]);var xt;!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"}(xt||(xt={}));const Ct=new Map([[xt.ID,"tb.rulenode.entity-details-id"],[xt.TITLE,"tb.rulenode.entity-details-title"],[xt.COUNTRY,"tb.rulenode.entity-details-country"],[xt.STATE,"tb.rulenode.entity-details-state"],[xt.CITY,"tb.rulenode.entity-details-city"],[xt.ZIP,"tb.rulenode.entity-details-zip"],[xt.ADDRESS,"tb.rulenode.entity-details-address"],[xt.ADDRESS2,"tb.rulenode.entity-details-address2"],[xt.PHONE,"tb.rulenode.entity-details-phone"],[xt.EMAIL,"tb.rulenode.entity-details-email"],[xt.ADDITIONAL_INFO,"tb.rulenode.entity-details-additional_info"]]);var St;!function(e){e.FIRST="FIRST",e.LAST="LAST",e.ALL="ALL"}(St||(St={}));const Tt=new Map([[St.FIRST,"tb.rulenode.first"],[St.LAST,"tb.rulenode.last"],[St.ALL,"tb.rulenode.all"]]),It=new Map([[St.FIRST,"tb.rulenode.first-mode-hint"],[St.LAST,"tb.rulenode.last-mode-hint"],[St.ALL,"tb.rulenode.all-mode-hint"]]);var Et,Ft;!function(e){e.ASC="ASC",e.DESC="DESC"}(Et||(Et={})),function(e){e.ATTRIBUTES="ATTRIBUTES",e.LATEST_TELEMETRY="LATEST_TELEMETRY",e.FIELDS="FIELDS"}(Ft||(Ft={}));const qt=new Map([[Ft.ATTRIBUTES,"tb.rulenode.attributes"],[Ft.LATEST_TELEMETRY,"tb.rulenode.latest-telemetry"],[Ft.FIELDS,"tb.rulenode.fields"]]),At=new Map([[Ft.ATTRIBUTES,"tb.rulenode.add-mapped-attribute-to"],[Ft.LATEST_TELEMETRY,"tb.rulenode.add-mapped-latest-telemetry-to"],[Ft.FIELDS,"tb.rulenode.add-mapped-fields-to"]]),kt=new Map([[Et.ASC,"tb.rulenode.ascending"],[Et.DESC,"tb.rulenode.descending"]]);var Nt;!function(e){e.STANDARD="STANDARD",e.FIFO="FIFO"}(Nt||(Nt={}));const wt=new Map([[Nt.STANDARD,"tb.rulenode.sqs-queue-standard"],[Nt.FIFO,"tb.rulenode.sqs-queue-fifo"]]),Mt=["anonymous","basic","cert.PEM"],Bt=new Map([["anonymous","tb.rulenode.credentials-anonymous"],["basic","tb.rulenode.credentials-basic"],["cert.PEM","tb.rulenode.credentials-pem"]]),Vt=["sas","cert.PEM"],Ot=new Map([["sas","tb.rulenode.credentials-sas"],["cert.PEM","tb.rulenode.credentials-pem"]]);var Dt;!function(e){e.GET="GET",e.POST="POST",e.PUT="PUT",e.DELETE="DELETE"}(Dt||(Dt={}));const Lt=["US-ASCII","ISO-8859-1","UTF-8","UTF-16BE","UTF-16LE","UTF-16"],Pt=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 Rt;!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"}(Rt||(Rt={}));const _t=new Map([[Rt.CUSTOM,{value:Rt.CUSTOM,name:"Custom Function",description:"Use this function to specify complex mathematical expression.",minArgs:1,maxArgs:16}],[Rt.ADD,{value:Rt.ADD,name:"Addition",description:"x + y",minArgs:2,maxArgs:2}],[Rt.SUB,{value:Rt.SUB,name:"Subtraction",description:"x - y",minArgs:2,maxArgs:2}],[Rt.MULT,{value:Rt.MULT,name:"Multiplication",description:"x * y",minArgs:2,maxArgs:2}],[Rt.DIV,{value:Rt.DIV,name:"Division",description:"x / y",minArgs:2,maxArgs:2}],[Rt.SIN,{value:Rt.SIN,name:"Sine",description:"Returns the trigonometric sine of an angle in radians.",minArgs:1,maxArgs:1}],[Rt.SINH,{value:Rt.SINH,name:"Hyperbolic sine",description:"Returns the hyperbolic sine of an argument.",minArgs:1,maxArgs:1}],[Rt.COS,{value:Rt.COS,name:"Cosine",description:"Returns the trigonometric cosine of an angle in radians.",minArgs:1,maxArgs:1}],[Rt.COSH,{value:Rt.COSH,name:"Hyperbolic cosine",description:"Returns the hyperbolic cosine of an argument.",minArgs:1,maxArgs:1}],[Rt.TAN,{value:Rt.TAN,name:"Tangent",description:"Returns the trigonometric tangent of an angle in radians",minArgs:1,maxArgs:1}],[Rt.TANH,{value:Rt.TANH,name:"Hyperbolic tangent",description:"Returns the hyperbolic tangent of an argument",minArgs:1,maxArgs:1}],[Rt.ACOS,{value:Rt.ACOS,name:"Arc cosine",description:"Returns the arc cosine of an argument",minArgs:1,maxArgs:1}],[Rt.ASIN,{value:Rt.ASIN,name:"Arc sine",description:"Returns the arc sine of an argument",minArgs:1,maxArgs:1}],[Rt.ATAN,{value:Rt.ATAN,name:"Arc tangent",description:"Returns the arc tangent of an argument",minArgs:1,maxArgs:1}],[Rt.ATAN2,{value:Rt.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}],[Rt.EXP,{value:Rt.EXP,name:"Exponential",description:"Returns Euler's number e raised to the power of an argument",minArgs:1,maxArgs:1}],[Rt.EXPM1,{value:Rt.EXPM1,name:"Exponential minus one",description:"Returns Euler's number e raised to the power of an argument minus one",minArgs:1,maxArgs:1}],[Rt.SQRT,{value:Rt.SQRT,name:"Square",description:"Returns the correctly rounded positive square root of an argument",minArgs:1,maxArgs:1}],[Rt.CBRT,{value:Rt.CBRT,name:"Cube root",description:"Returns the cube root of an argument",minArgs:1,maxArgs:1}],[Rt.GET_EXP,{value:Rt.GET_EXP,name:"Get exponent",description:"Returns the unbiased exponent used in the representation of an argument",minArgs:1,maxArgs:1}],[Rt.HYPOT,{value:Rt.HYPOT,name:"Square root",description:"Returns the square root of the squares of the arguments",minArgs:2,maxArgs:2}],[Rt.LOG,{value:Rt.LOG,name:"Logarithm",description:"Returns the natural logarithm of an argument",minArgs:1,maxArgs:1}],[Rt.LOG10,{value:Rt.LOG10,name:"Base 10 logarithm",description:"Returns the base 10 logarithm of an argument",minArgs:1,maxArgs:1}],[Rt.LOG1P,{value:Rt.LOG1P,name:"Logarithm of the sum",description:"Returns the natural logarithm of the sum of an argument",minArgs:1,maxArgs:1}],[Rt.CEIL,{value:Rt.CEIL,name:"Ceiling",description:"Returns the smallest (closest to negative infinity) of an argument",minArgs:1,maxArgs:1}],[Rt.FLOOR,{value:Rt.FLOOR,name:"Floor",description:"Returns the largest (closest to positive infinity) of an argument",minArgs:1,maxArgs:1}],[Rt.FLOOR_DIV,{value:Rt.FLOOR_DIV,name:"Floor division",description:"Returns the largest (closest to positive infinity) of the arguments",minArgs:2,maxArgs:2}],[Rt.FLOOR_MOD,{value:Rt.FLOOR_MOD,name:"Floor modulus",description:"Returns the floor modulus of the arguments",minArgs:2,maxArgs:2}],[Rt.ABS,{value:Rt.ABS,name:"Absolute",description:"Returns the absolute value of an argument",minArgs:1,maxArgs:1}],[Rt.MIN,{value:Rt.MIN,name:"Min",description:"Returns the smaller of the arguments",minArgs:2,maxArgs:2}],[Rt.MAX,{value:Rt.MAX,name:"Max",description:"Returns the greater of the arguments",minArgs:2,maxArgs:2}],[Rt.POW,{value:Rt.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}],[Rt.SIGNUM,{value:Rt.SIGNUM,name:"Sign of a real number",description:"Returns the signum function of the argument",minArgs:1,maxArgs:1}],[Rt.RAD,{value:Rt.RAD,name:"Radian",description:"Converts an angle measured in degrees to an approximately equivalent angle measured in radians",minArgs:1,maxArgs:1}],[Rt.DEG,{value:Rt.DEG,name:"Degrees",description:"Converts an angle measured in radians to an approximately equivalent angle measured in degrees.",minArgs:1,maxArgs:1}]]);var jt,Gt,Kt;!function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES",e.CONSTANT="CONSTANT"}(jt||(jt={})),function(e){e.MESSAGE_BODY="MESSAGE_BODY",e.MESSAGE_METADATA="MESSAGE_METADATA",e.ATTRIBUTE="ATTRIBUTE",e.TIME_SERIES="TIME_SERIES"}(Gt||(Gt={})),function(e){e.DATA="DATA",e.METADATA="METADATA"}(Kt||(Kt={}));const Ut=new Map([[Kt.DATA,"tb.rulenode.message-to-metadata"],[Kt.METADATA,"tb.rulenode.metadata-to-message"]]),Ht=(new Map([[Kt.DATA,"tb.rulenode.from-message"],[Kt.METADATA,"tb.rulenode.from-metadata"]]),new Map([[Kt.DATA,"tb.rulenode.message"],[Kt.METADATA,"tb.rulenode.metadata"]])),zt=new Map([[Kt.DATA,"tb.rulenode.message"],[Kt.METADATA,"tb.rulenode.message-metadata"]]),$t=new Map([[jt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Fetch argument value from incoming message"}],[jt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Fetch argument value from incoming message metadata"}],[jt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Fetch attribute value from database"}],[jt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Fetch latest time-series value from database"}],[jt.CONSTANT,{name:"tb.rulenode.constant-type",description:"Define constant value"}]]),Qt=new Map([[Gt.MESSAGE_BODY,{name:"tb.rulenode.message-body-type",description:"Add result to the outgoing message"}],[Gt.MESSAGE_METADATA,{name:"tb.rulenode.message-metadata-type",description:"Add result to the outgoing message metadata"}],[Gt.ATTRIBUTE,{name:"tb.rulenode.attribute-type",description:"Store result as an entity attribute in the database"}],[Gt.TIME_SERIES,{name:"tb.rulenode.time-series-type",description:"Store result as an entity time-series in the database"}]]),Jt=["x","y","z","a","b","c","d","k","l","m","n","o","p","r","s","t"];var Yt,Wt;!function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE",e.CLIENT_SCOPE="CLIENT_SCOPE"}(Yt||(Yt={})),function(e){e.SHARED_SCOPE="SHARED_SCOPE",e.SERVER_SCOPE="SERVER_SCOPE"}(Wt||(Wt={}));const Xt=new Map([[Yt.SHARED_SCOPE,"tb.rulenode.shared-scope"],[Yt.SERVER_SCOPE,"tb.rulenode.server-scope"],[Yt.CLIENT_SCOPE,"tb.rulenode.client-scope"]]);var Zt;!function(e){e.ON_FIRST_MESSAGE="ON_FIRST_MESSAGE",e.ON_EACH_MESSAGE="ON_EACH_MESSAGE"}(Zt||(Zt={}));const en=new Map([[Zt.ON_EACH_MESSAGE,{value:!0,name:"tb.rulenode.presence-monitoring-strategy-on-each-message"}],[Zt.ON_FIRST_MESSAGE,{value:!1,name:"tb.rulenode.presence-monitoring-strategy-on-first-message"}]]),tn=2147483648,nn=e=>({perimeterKeyName:e});function rn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.latitude-field-name-required")," "))}function an(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.longitude-field-name-required")," "))}function on(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",22),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.perimeterTypeTranslationMap.get(e))," ")}}function ln(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.perimeter-key-name-required")," "))}function sn(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",23)(1,"mat-label"),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",24),t.ɵɵtemplate(5,ln,3,3,"mat-error",6),t.ɵɵelementStart(6,"mat-hint"),t.ɵɵtext(7),t.ɵɵpipe(8,"translate"),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(3,3,"tb.rulenode.perimeter-key-name")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("perimeterKeyName").hasError("required")),t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(8,5,"tb.rulenode.perimeter-key-name-hint"))}}function pn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.circle-center-latitude-required")," "))}function mn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.circle-center-longitude-required")," "))}function dn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.range-required")," "))}function un(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",22),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.rangeUnitTranslationMap.get(e))," ")}}function cn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.range-units-required")," "))}function fn(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",9)(1,"div",3)(2,"mat-form-field",25)(3,"mat-label"),t.ɵɵtext(4),t.ɵɵpipe(5,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(6,"input",26),t.ɵɵtemplate(7,pn,3,3,"mat-error",6),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-form-field",25)(9,"mat-label"),t.ɵɵtext(10),t.ɵɵpipe(11,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(12,"input",27),t.ɵɵtemplate(13,mn,3,3,"mat-error",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(14,"div",3)(15,"mat-form-field",25)(16,"mat-label"),t.ɵɵtext(17),t.ɵɵpipe(18,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(19,"input",28),t.ɵɵtemplate(20,dn,3,3,"mat-error",6),t.ɵɵelementEnd(),t.ɵɵelementStart(21,"mat-form-field",25)(22,"mat-label"),t.ɵɵtext(23),t.ɵɵpipe(24,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(25,"mat-select",29),t.ɵɵtemplate(26,un,3,4,"mat-option",12),t.ɵɵelementEnd(),t.ɵɵtemplate(27,cn,3,3,"mat-error",6),t.ɵɵelementEnd()()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(5,9,"tb.rulenode.circle-center-latitude")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("centerLatitude").hasError("required")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(11,11,"tb.rulenode.circle-center-longitude")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("centerLongitude").hasError("required")),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(18,13,"tb.rulenode.range")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("range").hasError("required")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(24,15,"tb.rulenode.range-units")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",e.rangeUnits),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("rangeUnit").hasError("required"))}}function gn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.polygon-definition-required")," "))}function hn(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",9)(1,"mat-form-field",30)(2,"mat-label",31),t.ɵɵtext(3,"tb.rulenode.polygon-definition"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",32),t.ɵɵelementStart(5,"mat-icon",33),t.ɵɵpipe(6,"translate"),t.ɵɵtext(7," help "),t.ɵɵelementEnd(),t.ɵɵtemplate(8,gn,3,3,"mat-error",6),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(5),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(6,2,"tb.rulenode.polygon-definition-hint")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("polygonsDefinition").hasError("required"))}}function yn(e,n){if(1&e&&(t.ɵɵelementStart(0,"tb-toggle-option",22),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",r.presenceMonitoringStrategies.get(e).value),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.presenceMonitoringStrategies.get(e).name)," ")}}function bn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-inside-duration-value-required")," "))}function vn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.time-value-range")," "))}function xn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.time-value-range")," "))}function Cn(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",22),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.timeUnitsTranslationMap.get(e))," ")}}function Sn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-outside-duration-value-required")," "))}function Tn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.time-value-range")," "))}function In(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.time-value-range")," "))}function En(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",22),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.timeUnitsTranslationMap.get(e))," ")}}function Fn(e,n){if(1&e&&(t.ɵɵelementStart(0,"div")(1,"div",34)(2,"mat-form-field",35)(3,"mat-label",31),t.ɵɵtext(4,"tb.rulenode.min-inside-duration"),t.ɵɵelementEnd(),t.ɵɵelement(5,"input",36),t.ɵɵtemplate(6,bn,3,3,"mat-error",6)(7,vn,3,3,"mat-error",6)(8,xn,3,3,"mat-error",6),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"mat-form-field",35)(10,"mat-label",31),t.ɵɵtext(11,"tb.rulenode.min-inside-duration-time-unit"),t.ɵɵelementEnd(),t.ɵɵelementStart(12,"mat-select",37),t.ɵɵtemplate(13,Cn,3,4,"mat-option",12),t.ɵɵelementEnd()()(),t.ɵɵelementStart(14,"div",34)(15,"mat-form-field",35)(16,"mat-label",31),t.ɵɵtext(17,"tb.rulenode.min-outside-duration"),t.ɵɵelementEnd(),t.ɵɵelement(18,"input",38),t.ɵɵtemplate(19,Sn,3,3,"mat-error",6)(20,Tn,3,3,"mat-error",6)(21,In,3,3,"mat-error",6),t.ɵɵelementEnd(),t.ɵɵelementStart(22,"mat-form-field",35)(23,"mat-label",31),t.ɵɵtext(24,"tb.rulenode.min-outside-duration-time-unit"),t.ɵɵelementEnd(),t.ɵɵelementStart(25,"mat-select",39),t.ɵɵtemplate(26,En,3,4,"mat-option",12),t.ɵɵelementEnd()()()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(6),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("minInsideDuration").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("minInsideDuration").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("minInsideDuration").hasError("max")),t.ɵɵadvance(5),t.ɵɵproperty("ngForOf",e.timeUnits),t.ɵɵadvance(6),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("minOutsideDuration").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("minOutsideDuration").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.geoActionConfigForm.get("minOutsideDuration").hasError("max")),t.ɵɵadvance(5),t.ɵɵproperty("ngForOf",e.timeUnits)}}class qn extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=ft,this.perimeterTypes=Object.keys(ft),this.perimeterTypeTranslationMap=gt,this.rangeUnits=Object.keys(bt),this.rangeUnitTranslationMap=vt,this.presenceMonitoringStrategies=en,this.presenceMonitoringStrategyKeys=Array.from(this.presenceMonitoringStrategies.keys()),this.timeUnits=Object.keys(ht),this.timeUnitsTranslationMap=yt,this.defaultPaddingEnable=!0}configForm(){return this.geoActionConfigForm}onConfigurationSet(e){this.geoActionConfigForm=this.fb.group({reportPresenceStatusOnEachMessage:[!e||e.reportPresenceStatusOnEachMessage,[N.required]],latitudeKeyName:[e?e.latitudeKeyName:null,[N.required]],longitudeKeyName:[e?e.longitudeKeyName:null,[N.required]],perimeterType:[e?e.perimeterType:null,[N.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,[N.required,N.min(1),N.max(2147483647)]],minInsideDurationTimeUnit:[e?e.minInsideDurationTimeUnit:null,[N.required]],minOutsideDuration:[e?e.minOutsideDuration:null,[N.required,N.min(1),N.max(2147483647)]],minOutsideDurationTimeUnit:[e?e.minOutsideDurationTimeUnit:null,[N.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([N.required]):this.geoActionConfigForm.get("perimeterKeyName").setValidators([]),t||n!==ft.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([N.required,N.min(-90),N.max(90)]),this.geoActionConfigForm.get("centerLongitude").setValidators([N.required,N.min(-180),N.max(180)]),this.geoActionConfigForm.get("range").setValidators([N.required,N.min(0)]),this.geoActionConfigForm.get("rangeUnit").setValidators([N.required]),this.defaultPaddingEnable=!1),t||n!==ft.POLYGON?this.geoActionConfigForm.get("polygonsDefinition").setValidators([]):this.geoActionConfigForm.get("polygonsDefinition").setValidators([N.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})}static{this.ɵfac=function(e){return new(e||qn)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:qn,selectors:[["tb-action-node-gps-geofencing-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:52,vars:42,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],[1,"tb-form-panel","stroked"],["translate","",1,"tb-form-panel-title"],[1,"flex","flex-row","gap-4"],[1,"mat-block","max-w-50%","flex-full"],["matInput","","formControlName","latitudeKeyName","required",""],[4,"ngIf"],["matInput","","formControlName","longitudeKeyName","required",""],["translate","",1,"tb-form-hint","tb-primary-fill"],[1,"flex","flex-col"],["hideRequiredMarker","",1,"mat-block","flex-1"],["formControlName","perimeterType"],[3,"value",4,"ngFor","ngForOf"],[1,"tb-form-row","no-border","no-padding","slide-toggle",3,"tb-hint-tooltip-icon"],["formControlName","fetchPerimeterInfoFromMessageMetadata",1,"mat-slide"],["class","mat-block",4,"ngIf"],["class","flex flex-col",4,"ngIf"],[1,"tb-form-panel","stroked","no-padding-bottom"],[1,"flex","flex-col","items-stretch","justify-between","gt-sm:flex-row","lt-md:gap-4"],[1,"tb-form-panel-title"],["formControlName","reportPresenceStatusOnEachMessage","appearance","fill",1,"fetch-to-data-toggle"],[1,"tb-form-hint","tb-primary-fill"],[3,"value"],[1,"mat-block"],["matInput","","formControlName","perimeterKeyName","required",""],[1,"flex-1"],["type","number","min","-90","max","90","step","0.1","matInput","","formControlName","centerLatitude","required",""],["type","number","min","-180","max","180","step","0.1","matInput","","formControlName","centerLongitude","required",""],["type","number","min","0","step","0.1","matInput","","formControlName","range","required",""],["formControlName","rangeUnit","required",""],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["matInput","","formControlName","polygonsDefinition","required",""],["matSuffix","","aria-hidden","false","aria-label","help-icon","color","primary",1,"margin-8","cursor-pointer",3,"matTooltip"],[1,"flex","flex-col","gt-sm:flex-row","gt-sm:gap-2"],[1,"mat-block","flex-1"],["type","number","step","1","min","1","max","2147483647","matInput","","formControlName","minInsideDuration","required",""],["formControlName","minInsideDurationTimeUnit","required",""],["type","number","step","1","min","1","max","2147483647","matInput","","formControlName","minOutsideDuration","required",""],["formControlName","minOutsideDurationTimeUnit","required",""]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"section",1)(2,"div",2),t.ɵɵtext(3,"tb.rulenode.coordinate-field-names"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"section")(5,"div",3)(6,"mat-form-field",4)(7,"mat-label"),t.ɵɵtext(8),t.ɵɵpipe(9,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(10,"input",5),t.ɵɵtemplate(11,rn,3,3,"mat-error",6),t.ɵɵelementEnd(),t.ɵɵelementStart(12,"mat-form-field",4)(13,"mat-label"),t.ɵɵtext(14),t.ɵɵpipe(15,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(16,"input",7),t.ɵɵtemplate(17,an,3,3,"mat-error",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(18,"div",8),t.ɵɵtext(19,"tb.rulenode.coordinate-field-hint"),t.ɵɵelementEnd()()(),t.ɵɵelementStart(20,"section",1)(21,"div",2),t.ɵɵtext(22,"tb.rulenode.geofence-configuration"),t.ɵɵelementEnd(),t.ɵɵelementStart(23,"section",9)(24,"mat-form-field",10)(25,"mat-label"),t.ɵɵtext(26),t.ɵɵpipe(27,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(28,"mat-select",11),t.ɵɵtemplate(29,on,3,4,"mat-option",12),t.ɵɵelementEnd()(),t.ɵɵelementStart(30,"div",13),t.ɵɵpipe(31,"translate"),t.ɵɵpipe(32,"translate"),t.ɵɵelementStart(33,"mat-slide-toggle",14),t.ɵɵtext(34),t.ɵɵpipe(35,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(36,sn,9,7,"mat-form-field",15)(37,fn,28,17,"div",16)(38,hn,9,4,"div",16),t.ɵɵelementEnd()(),t.ɵɵelementStart(39,"section",17)(40,"div",18)(41,"div",19),t.ɵɵtext(42),t.ɵɵpipe(43,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(44,"tb-toggle-select",20),t.ɵɵtemplate(45,yn,3,4,"tb-toggle-option",12),t.ɵɵelementEnd()(),t.ɵɵelementStart(46,"div",21),t.ɵɵtext(47),t.ɵɵpipe(48,"translate"),t.ɵɵpipe(49,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(50,"section",9),t.ɵɵtemplate(51,Fn,27,8,"div",6),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.geoActionConfigForm),t.ɵɵadvance(8),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(9,18,"tb.rulenode.latitude-field-name")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.geoActionConfigForm.get("latitudeKeyName").hasError("required")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(15,20,"tb.rulenode.longitude-field-name")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.geoActionConfigForm.get("longitudeKeyName").hasError("required")),t.ɵɵadvance(3),t.ɵɵclassProp("no-padding-bottom",!n.defaultPaddingEnable),t.ɵɵadvance(6),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(27,22,"tb.rulenode.perimeter-type")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.perimeterTypes),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",n.geoActionConfigForm.get("perimeterType").value===n.perimeterType.CIRCLE?t.ɵɵpipeBind2(31,24,"tb.rulenode.fetch-circle-parameter-info-from-metadata-hint",t.ɵɵpureFunction1(38,nn,n.geoActionConfigForm.get("perimeterKeyName").valid?n.geoActionConfigForm.get("perimeterKeyName").value:"ss_perimeter")):t.ɵɵpipeBind2(32,27,"tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint",t.ɵɵpureFunction1(40,nn,n.geoActionConfigForm.get("perimeterKeyName").valid?n.geoActionConfigForm.get("perimeterKeyName").value:"ss_perimeter"))),t.ɵɵadvance(4),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(35,30,"tb.rulenode.fetch-perimeter-info-from-metadata")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.geoActionConfigForm.get("perimeterType").value===n.perimeterType.CIRCLE&&!n.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.geoActionConfigForm.get("perimeterType").value===n.perimeterType.POLYGON&&!n.geoActionConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(43,32,"tb.rulenode.presence-monitoring-strategy")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.presenceMonitoringStrategyKeys),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",!1===n.geoActionConfigForm.get("reportPresenceStatusOnEachMessage").value?t.ɵɵpipeBind1(48,34,"tb.rulenode.presence-monitoring-strategy-on-first-message-hint"):t.ɵɵpipeBind1(49,36,"tb.rulenode.presence-monitoring-strategy-on-each-message-hint")," "),t.ɵɵadvance(4),t.ɵɵproperty("ngIf",!1===n.geoActionConfigForm.get("reportPresenceStatusOnEachMessage").value))},dependencies:t.ɵɵgetComponentDepsFactory(qn),styles:["[_nghost-%COMP%] .slide-toggle[_ngcontent-%COMP%]{margin-bottom:18px}"]})}}e("GpsGeoActionConfigComponent",qn);const An=["jsFuncComponent"],kn=["tbelFuncComponent"],Nn=()=>["msg","metadata","msgType"];function wn(e,n){1&e&&t.ɵɵelement(0,"tb-script-lang",8)}function Mn(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",9,0)(2,"button",10),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",11),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(4,Nn)),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,2,e.testScriptLabel))}}function Bn(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",12,1)(2,"button",10),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",11),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(6,Nn))("disableUndefinedCheck",!0)("scriptLanguage",e.scriptLanguage.TBEL),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,4,e.testScriptLabel))}}class Vn extends i{constructor(e,t,r,a){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=r,this.translate=a,this.tbelEnabled=D(this.store).tbelEnabled,this.scriptLanguage=s,this.changeScript=new n,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:s.JS,[N.required]],jsScript:[e?e.jsScript:null,[]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.logConfigForm.get("scriptLang").value;t!==s.TBEL||this.tbelEnabled||(t=s.JS,this.logConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.logConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.logConfigForm.get("jsScript").setValidators(t===s.JS?[N.required]:[]),this.logConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.logConfigForm.get("tbelScript").setValidators(t===s.TBEL?[N.required]:[]),this.logConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=s.JS)),e}testScript(e){const t=this.logConfigForm.get("scriptLang").value,n=t===s.JS?"jsScript":"tbelScript",r=t===s.JS?"rulenode/log_node_script_fn":"rulenode/tbel/log_node_script_fn",a=this.logConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(a,"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===s.JS&&this.jsFuncComponent.validateOnSubmit()}static{this.ɵfac=function(e){return new(e||Vn)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder),t.ɵɵdirectiveInject(L.NodeScriptTestService),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Vn,selectors:[["tb-action-node-log-config"]],viewQuery:function(e,n){if(1&e&&(t.ɵɵviewQuery(An,5),t.ɵɵviewQuery(kn,5)),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.jsFuncComponent=e.first),t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.tbelFuncComponent=e.first)}},features:[t.ɵɵInheritDefinitionFeature],decls:8,vars:7,consts:[["jsFuncComponent",""],["tbelFuncComponent",""],[1,"flex","flex-col",3,"formGroup"],["formControlName","scriptLang",4,"ngIf"],["formControlName","jsScript","functionName","ToString","helpId","rulenode/log_node_script_fn","noValidate","true",3,"functionArgs",4,"ngIf"],["formControlName","tbelScript","functionName","ToString","helpId","rulenode/tbel/log_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage",4,"ngIf"],[1,"flex","flex-row"],["mat-button","","mat-raised-button","","color","primary",3,"click"],["formControlName","scriptLang"],["formControlName","jsScript","functionName","ToString","helpId","rulenode/log_node_script_fn","noValidate","true",3,"functionArgs"],["toolbarSuffixButton","","mat-icon-button","","matTooltipPosition","above",1,"tb-mat-32",3,"click","matTooltip"],["color","primary",1,"material-icons"],["formControlName","tbelScript","functionName","ToString","helpId","rulenode/tbel/log_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",2),t.ɵɵtemplate(1,wn,1,0,"tb-script-lang",3)(2,Mn,6,5,"tb-js-func",4)(3,Bn,6,7,"tb-js-func",5),t.ɵɵelementStart(4,"div",6)(5,"button",7),t.ɵɵlistener("click",(function(){return n.testScript()})),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.logConfigForm),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.tbelEnabled),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.logConfigForm.get("scriptLang").value===n.scriptLanguage.JS),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.logConfigForm.get("scriptLang").value===n.scriptLanguage.TBEL),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(7,5,n.testScriptLabel)," "))},dependencies:t.ɵɵgetComponentDepsFactory(Vn),encapsulation:2})}}function On(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.interval-seconds-required")," "))}function Dn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-interval-seconds-message")," "))}function Ln(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.output-timeseries-key-prefix-required")," "))}e("LogConfigComponent",Vn);class Pn extends i{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,[N.required,N.min(1)]],telemetryPrefix:[e?e.telemetryPrefix:null,[N.required]]})}static{this.ɵfac=function(e){return new(e||Pn)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Pn,selectors:[["tb-action-node-msg-count-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:12,vars:4,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"mat-block"],["translate",""],["required","","type","number","min","1","step","1","matInput","","formControlName","interval"],[4,"ngIf"],["required","","matInput","","formControlName","telemetryPrefix"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.interval-seconds"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,On,3,3,"mat-error",4)(6,Dn,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(7,"mat-form-field",1)(8,"mat-label",2),t.ɵɵtext(9,"tb.rulenode.output-timeseries-key-prefix"),t.ɵɵelementEnd(),t.ɵɵelement(10,"input",5),t.ɵɵtemplate(11,Ln,3,3,"mat-error",4),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.msgCountConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.msgCountConfigForm.get("interval").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.msgCountConfigForm.get("interval").hasError("min")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.msgCountConfigForm.get("telemetryPrefix").hasError("required")))},dependencies:t.ɵɵgetComponentDepsFactory(Pn),encapsulation:2})}}function Rn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.period-seconds-required")," "))}function _n(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-period-0-seconds-message")," "))}function jn(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",5)(1,"mat-label",6),t.ɵɵtext(2,"tb.rulenode.period-seconds"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",9),t.ɵɵtemplate(4,Rn,3,3,"mat-error",8)(5,_n,3,3,"mat-error",8),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵproperty("ngIf",e.msgDelayConfigForm.get("periodInSeconds").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.msgDelayConfigForm.get("periodInSeconds").hasError("min"))}}function Gn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.period-in-seconds-pattern-required")," "))}function Kn(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",10)(1,"mat-label",6),t.ɵɵtext(2,"tb.rulenode.period-in-seconds-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",11),t.ɵɵtemplate(4,Gn,3,3,"mat-error",8),t.ɵɵelementStart(5,"mat-hint",6),t.ɵɵtext(6,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵproperty("ngIf",e.msgDelayConfigForm.get("periodInSecondsPattern").hasError("required"))}}function Un(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-pending-messages-required")," "))}function Hn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-pending-messages-range")," "))}function zn(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-pending-messages-range")," "))}e("MsgCountConfigComponent",Pn);class $n extends i{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,[N.required,N.min(1),N.max(1e5)]]})}validatorTriggers(){return["useMetadataPeriodInSecondsPatterns"]}updateValidators(e){this.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value?(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([N.required]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([])):(this.msgDelayConfigForm.get("periodInSecondsPattern").setValidators([]),this.msgDelayConfigForm.get("periodInSeconds").setValidators([N.required,N.min(0)])),this.msgDelayConfigForm.get("periodInSecondsPattern").updateValueAndValidity({emitEvent:e}),this.msgDelayConfigForm.get("periodInSeconds").updateValueAndValidity({emitEvent:e})}static{this.ɵfac=function(e){return new(e||$n)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:$n,selectors:[["tb-action-node-msg-delay-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:16,vars:9,consts:[["periodInSecondsPattern",""],[1,"flex","flex-col",3,"formGroup"],["formControlName","useMetadataPeriodInSecondsPatterns"],["translate","",1,"tb-hint"],["class","mat-block",4,"ngIf","ngIfElse"],[1,"mat-block"],["translate",""],["required","","type","number","min","1","max","100000","step","1","matInput","","formControlName","maxPendingMsgs"],[4,"ngIf"],["required","","type","number","min","0","step","1","matInput","","formControlName","periodInSeconds"],["subscriptSizing","dynamic",1,"mat-block"],["required","","matInput","","formControlName","periodInSecondsPattern"]],template:function(e,n){if(1&e&&(t.ɵɵelementStart(0,"section",1)(1,"mat-checkbox",2),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"div",3),t.ɵɵtext(5,"tb.rulenode.use-metadata-period-in-seconds-patterns-hint"),t.ɵɵelementEnd(),t.ɵɵtemplate(6,jn,6,2,"mat-form-field",4)(7,Kn,7,1,"ng-template",null,0,t.ɵɵtemplateRefExtractor),t.ɵɵelementStart(9,"mat-form-field",5)(10,"mat-label",6),t.ɵɵtext(11,"tb.rulenode.max-pending-messages"),t.ɵɵelementEnd(),t.ɵɵelement(12,"input",7),t.ɵɵtemplate(13,Un,3,3,"mat-error",8)(14,Hn,3,3,"mat-error",8)(15,zn,3,3,"mat-error",8),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵreference(8);t.ɵɵproperty("formGroup",n.msgDelayConfigForm),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(3,7,"tb.rulenode.use-metadata-period-in-seconds-patterns")," "),t.ɵɵadvance(4),t.ɵɵproperty("ngIf",!0!==n.msgDelayConfigForm.get("useMetadataPeriodInSecondsPatterns").value)("ngIfElse",e),t.ɵɵadvance(7),t.ɵɵproperty("ngIf",n.msgDelayConfigForm.get("maxPendingMsgs").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.msgDelayConfigForm.get("maxPendingMsgs").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.msgDelayConfigForm.get("maxPendingMsgs").hasError("max"))}},dependencies:t.ɵɵgetComponentDepsFactory($n),encapsulation:2})}}e("MsgDelayConfigComponent",$n);const Qn=()=>({standalone:!0});function Jn(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",10),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.telemetryTypeTranslationsMap.get(e))," ")}}class Yn extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(o),this.telemetryTypeTranslationsMap=l}configForm(){return this.pushToCloudConfigForm}onConfigurationSet(e){this.pushToCloudConfigForm=this.fb.group({scope:[e?e.scope:null,[N.required]]})}static{this.ɵfac=function(e){return new(e||Yn)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Yn,selectors:[["tb-action-node-push-to-cloud-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:19,vars:16,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],[1,"tb-form-panel","stroked"],[3,"hintText"],[1,"tb-form-row","no-border","no-padding","tb-standard-fields"],[1,"flex"],["required","","matInput","","formControlName","scope",1,"tb-entity-type-select"],[3,"value",4,"ngFor","ngForOf"],["type","text","matInput","","readonly","","disabled","",3,"ngModel","ngModelOptions"],["type","button","matSuffix","","mat-icon-button","","aria-label","Copy","ngxClipboard","",3,"cbContent","matTooltip"],["aria-hidden","false","aria-label","help-icon"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵelement(2,"tb-example-hint",2),t.ɵɵelementStart(3,"div",3)(4,"mat-form-field",4)(5,"mat-label"),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-select",5),t.ɵɵtemplate(9,Jn,3,4,"mat-option",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(10,"mat-form-field",4)(11,"mat-label"),t.ɵɵtext(12),t.ɵɵpipe(13,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(14,"input",7),t.ɵɵelementStart(15,"button",8),t.ɵɵpipe(16,"translate"),t.ɵɵelementStart(17,"mat-icon",9),t.ɵɵtext(18,"content_copy "),t.ɵɵelementEnd()()()()()()),2&e&&(t.ɵɵproperty("formGroup",n.pushToCloudConfigForm),t.ɵɵadvance(2),t.ɵɵproperty("hintText","tb.rulenode.attributes-scope-hint"),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(7,9,"tb.rulenode.attributes-scope")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.attributeScopes),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(13,11,"tb.rulenode.attributes-scope-value")),t.ɵɵadvance(2),t.ɵɵproperty("ngModel",n.pushToCloudConfigForm.get("scope").value)("ngModelOptions",t.ɵɵpureFunction0(15,Qn)),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(16,13,"tb.rulenode.attributes-scope-value-copy")),t.ɵɵproperty("cbContent",n.pushToCloudConfigForm.get("scope").value))},dependencies:t.ɵɵgetComponentDepsFactory(Yn),encapsulation:2})}}e("PushToCloudConfigComponent",Yn);const Wn=()=>({standalone:!0});function Xn(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",10),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.telemetryTypeTranslationsMap.get(e))," ")}}class Zn extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopes=Object.keys(o),this.telemetryTypeTranslationsMap=l}configForm(){return this.pushToEdgeConfigForm}onConfigurationSet(e){this.pushToEdgeConfigForm=this.fb.group({scope:[e?e.scope:null,[N.required]]})}static{this.ɵfac=function(e){return new(e||Zn)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Zn,selectors:[["tb-action-node-push-to-edge-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:19,vars:16,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],[1,"tb-form-panel","stroked"],[3,"hintText"],[1,"tb-form-row","no-border","no-padding","tb-standard-fields"],[1,"flex"],["required","","matInput","","formControlName","scope",1,"tb-entity-type-select"],[3,"value",4,"ngFor","ngForOf"],["type","text","matInput","","readonly","","disabled","",3,"ngModel","ngModelOptions"],["type","button","matSuffix","","mat-icon-button","","aria-label","Copy","ngxClipboard","",3,"cbContent","matTooltip"],["aria-hidden","false","aria-label","help-icon"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵelement(2,"tb-example-hint",2),t.ɵɵelementStart(3,"div",3)(4,"mat-form-field",4)(5,"mat-label"),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-select",5),t.ɵɵtemplate(9,Xn,3,4,"mat-option",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(10,"mat-form-field",4)(11,"mat-label"),t.ɵɵtext(12),t.ɵɵpipe(13,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(14,"input",7),t.ɵɵelementStart(15,"button",8),t.ɵɵpipe(16,"translate"),t.ɵɵelementStart(17,"mat-icon",9),t.ɵɵtext(18,"content_copy "),t.ɵɵelementEnd()()()()()()),2&e&&(t.ɵɵproperty("formGroup",n.pushToEdgeConfigForm),t.ɵɵadvance(2),t.ɵɵproperty("hintText","tb.rulenode.attributes-scope-hint"),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(7,9,"tb.rulenode.attributes-scope")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.attributeScopes),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(13,11,"tb.rulenode.attributes-scope-value")),t.ɵɵadvance(2),t.ɵɵproperty("ngModel",n.pushToEdgeConfigForm.get("scope").value)("ngModelOptions",t.ɵɵpureFunction0(15,Wn)),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(16,13,"tb.rulenode.attributes-scope-value-copy")),t.ɵɵproperty("cbContent",n.pushToEdgeConfigForm.get("scope").value))},dependencies:t.ɵɵgetComponentDepsFactory(Zn),encapsulation:2})}}e("PushToEdgeConfigComponent",Zn);class er extends i{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,[]]})}static{this.ɵfac=function(e){return new(e||er)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:er,selectors:[["tb-action-node-rpc-reply-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:17,vars:2,consts:[[1,"tb-form-panel","stroked","no-padding-bottom",3,"formGroup"],["translate","",1,"tb-form-panel-title"],[3,"hintText"],[1,"tb-form-row","no-border","no-padding","tb-standard-fields","column-xs"],[1,"flex"],["translate",""],["matInput","","formControlName","serviceIdMetaDataAttribute"],["matInput","","formControlName","sessionIdMetaDataAttribute"],["matInput","","formControlName","requestIdMetaDataAttribute"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵtext(2,"tb.rulenode.reply-routing-configuration"),t.ɵɵelementEnd(),t.ɵɵelement(3,"tb-example-hint",2),t.ɵɵelementStart(4,"div",3)(5,"mat-form-field",4)(6,"mat-label",5),t.ɵɵtext(7,"tb.rulenode.service-id-metadata-attribute"),t.ɵɵelementEnd(),t.ɵɵelement(8,"input",6),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"mat-form-field",4)(10,"mat-label",5),t.ɵɵtext(11,"tb.rulenode.session-id-metadata-attribute"),t.ɵɵelementEnd(),t.ɵɵelement(12,"input",7),t.ɵɵelementEnd(),t.ɵɵelementStart(13,"mat-form-field",4)(14,"mat-label",5),t.ɵɵtext(15,"tb.rulenode.request-id-metadata-attribute"),t.ɵɵelementEnd(),t.ɵɵelement(16,"input",8),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.rpcReplyConfigForm),t.ɵɵadvance(3),t.ɵɵproperty("hintText","tb.rulenode.rpc-reply-routing-configuration-hint"))},dependencies:t.ɵɵgetComponentDepsFactory(er),encapsulation:2})}}function tr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.timeout-required")," "))}function nr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-timeout-message")," "))}e("RpcReplyConfigComponent",er);class rr extends i{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,[N.required,N.min(0)]]})}static{this.ɵfac=function(e){return new(e||rr)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:rr,selectors:[["tb-action-node-rpc-request-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:7,vars:3,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"mat-block","flex-1"],["translate",""],["type","number","min","0","step","1","matInput","","formControlName","timeoutInSeconds","required",""],[4,"ngIf"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.timeout-sec"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,tr,3,3,"mat-error",4)(6,nr,3,3,"mat-error",4),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.rpcRequestConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.rpcRequestConfigForm.get("timeoutInSeconds").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.rpcRequestConfigForm.get("timeoutInSeconds").hasError("min")))},dependencies:t.ɵɵgetComponentDepsFactory(rr),encapsulation:2})}}function ar(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.custom-table-name-required")," "))}function ir(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-default-ttl-message")," "))}function or(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.default-ttl-required")," "))}e("RpcRequestConfigComponent",rr);class lr extends i{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,[N.required,N.pattern(/.*\S.*/)]],fieldsMapping:[e?e.fieldsMapping:null,[N.required]],defaultTtl:[e?e.defaultTtl:0,[N.required,N.min(0)]]})}prepareOutputConfig(e){return e.tableName=e.tableName.trim(),e}static{this.ɵfac=function(e){return new(e||lr)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:lr,selectors:[["tb-action-node-custom-table-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:24,vars:26,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","tableName"],["aria-hidden","false","aria-label","help-icon","matSuffix","",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],[4,"ngIf"],["required","","formControlName","fieldsMapping",3,"labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText","hintText"],[1,"mat-block","flex-1"],["type","number","min","0","step","1","matInput","","formControlName","defaultTtl","required",""]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.custom-table-name"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵelementStart(5,"mat-icon",4),t.ɵɵpipe(6,"translate"),t.ɵɵtext(7," help "),t.ɵɵelementEnd(),t.ɵɵtemplate(8,ar,3,3,"mat-error",5),t.ɵɵelementEnd(),t.ɵɵelement(9,"tb-kv-map-config",6),t.ɵɵpipe(10,"translate"),t.ɵɵpipe(11,"translate"),t.ɵɵpipe(12,"translate"),t.ɵɵpipe(13,"translate"),t.ɵɵpipe(14,"translate"),t.ɵɵpipe(15,"translate"),t.ɵɵelementStart(16,"mat-form-field",7)(17,"mat-label",2),t.ɵɵtext(18,"tb.rulenode.default-ttl"),t.ɵɵelementEnd(),t.ɵɵelement(19,"input",8),t.ɵɵelementStart(20,"mat-hint",2),t.ɵɵtext(21,"tb.rulenode.default-ttl-zero-hint"),t.ɵɵelementEnd(),t.ɵɵtemplate(22,ir,3,3,"mat-error",5)(23,or,3,3,"mat-error",5),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.saveToCustomTableConfigForm),t.ɵɵadvance(5),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(6,12,"tb.rulenode.custom-table-hint")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.saveToCustomTableConfigForm.get("tableName").hasError("required")||n.saveToCustomTableConfigForm.get("tableName").hasError("pattern")),t.ɵɵadvance(),t.ɵɵproperty("labelText",t.ɵɵpipeBind1(10,14,"tb.rulenode.fields-mapping"))("requiredText",t.ɵɵpipeBind1(11,16,"tb.rulenode.fields-mapping-required"))("keyText",t.ɵɵpipeBind1(12,18,"tb.rulenode.message-field"))("keyRequiredText",t.ɵɵpipeBind1(13,20,"tb.rulenode.message-field-required"))("valText",t.ɵɵpipeBind1(14,22,"tb.rulenode.table-col"))("valRequiredText",t.ɵɵpipeBind1(15,24,"tb.rulenode.table-col-required"))("hintText","tb.rulenode.fields-mapping-hint"),t.ɵɵadvance(13),t.ɵɵproperty("ngIf",n.saveToCustomTableConfigForm.get("defaultTtl").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.saveToCustomTableConfigForm.get("defaultTtl").hasError("required")))},dependencies:t.ɵɵgetComponentDepsFactory(lr),encapsulation:2})}}function sr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.default-ttl-required")," "))}function pr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-default-ttl-message")," "))}e("SaveToCustomTableConfigComponent",lr);class mr extends i{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,[N.required,N.min(0)]],skipLatestPersistence:[!!e&&e.skipLatestPersistence,[]],useServerTs:[!!e&&e.useServerTs,[]]})}static{this.ɵfac=function(e){return new(e||mr)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:mr,selectors:[["tb-action-node-timeseries-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:21,vars:18,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],[1,"mat-block","flex-1"],["translate",""],["type","number","min","0","step","1","matInput","","formControlName","defaultTTL","required",""],["aria-hidden","false","aria-label","help-icon","matSuffix","",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],[4,"ngIf"],[1,"tb-form-panel","stroked"],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","useServerTs",1,"mat-slide"],["formControlName","skipLatestPersistence",1,"mat-slide"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.default-ttl"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵelementStart(5,"mat-icon",4),t.ɵɵpipe(6,"translate"),t.ɵɵtext(7," help "),t.ɵɵelementEnd(),t.ɵɵtemplate(8,sr,3,3,"mat-error",5)(9,pr,3,3,"mat-error",5),t.ɵɵelementEnd(),t.ɵɵelementStart(10,"div",6)(11,"div",7),t.ɵɵpipe(12,"translate"),t.ɵɵelementStart(13,"mat-slide-toggle",8),t.ɵɵtext(14),t.ɵɵpipe(15,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(16,"div",7),t.ɵɵpipe(17,"translate"),t.ɵɵelementStart(18,"mat-slide-toggle",9),t.ɵɵtext(19),t.ɵɵpipe(20,"translate"),t.ɵɵelementEnd()()()()),2&e&&(t.ɵɵproperty("formGroup",n.timeseriesConfigForm),t.ɵɵadvance(5),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(6,8,"tb.rulenode.default-ttl-hint")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.timeseriesConfigForm.get("defaultTTL").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.timeseriesConfigForm.get("defaultTTL").hasError("min")),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(12,10,"tb.rulenode.use-server-ts-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(15,12,"tb.rulenode.use-server-ts")," "),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(17,14,"tb.rulenode.skip-latest-persistence-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(20,16,"tb.rulenode.skip-latest-persistence")," "))},dependencies:t.ɵɵgetComponentDepsFactory(mr),encapsulation:2})}}function dr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.customer-name-pattern-required")," "))}function ur(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",6)(1,"mat-label",7),t.ɵɵtext(2,"tb.rulenode.customer-name-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",8),t.ɵɵtemplate(4,dr,3,3,"mat-error",9),t.ɵɵelementStart(5,"mat-hint",7),t.ɵɵtext(6,"tb.rulenode.customer-name-pattern-hint"),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵproperty("ngIf",e.unassignCustomerConfigForm.get("customerNamePattern").hasError("required")||e.unassignCustomerConfigForm.get("customerNamePattern").hasError("pattern"))}}e("TimeseriesConfigComponent",mr);class cr extends i{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.unassignCustomerConfigForm}prepareInputConfig(e){return{customerNamePattern:P(e?.customerNamePattern)?e.customerNamePattern:null,unassignFromCustomer:P(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([N.required,N.pattern(/.*\S.*/)]):this.unassignCustomerConfigForm.get("customerNamePattern").setValidators([]),this.unassignCustomerConfigForm.get("customerNamePattern").updateValueAndValidity({emitEvent:e})}prepareOutputConfig(e){return{customerNamePattern:e.unassignFromCustomer?e.customerNamePattern.trim():null}}static{this.ɵfac=function(e){return new(e||cr)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:cr,selectors:[["tb-action-node-un-assign-to-customer-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:9,vars:10,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"tb-form-panel","no-padding","no-border"],[1,"tb-form-panel","stroked"],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","unassignFromCustomer",1,"mat-slide"],["class","mat-block","subscriptSizing","dynamic",4,"ngIf"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","customerNamePattern"],[4,"ngIf"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2)(3,"div",3),t.ɵɵpipe(4,"translate"),t.ɵɵelementStart(5,"mat-slide-toggle",4),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(8,ur,7,1,"mat-form-field",5),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.unassignCustomerConfigForm),t.ɵɵadvance(2),t.ɵɵclassProp("no-padding-bottom",n.unassignCustomerConfigForm.get("unassignFromCustomer").value),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(4,6,"tb.rulenode.unassign-from-customer-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(7,8,"tb.rulenode.unassign-from-customer")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.unassignCustomerConfigForm.get("unassignFromCustomer").value))},dependencies:t.ɵɵgetComponentDepsFactory(cr),encapsulation:2})}}e("UnassignCustomerConfigComponent",cr);class fr extends i{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,[]]})}static{this.ɵfac=function(e){return new(e||fr)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:fr,selectors:[["tb-action-node-send-rest-api-call-reply-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:13,vars:2,consts:[[1,"tb-form-panel","stroked","no-padding-bottom",3,"formGroup"],["translate","",1,"tb-form-panel-title"],[3,"hintText"],[1,"tb-form-row","no-border","no-padding","tb-standard-fields","column-xs"],[1,"flex"],["translate",""],["matInput","","formControlName","serviceIdMetaDataAttribute"],["matInput","","formControlName","requestIdMetaDataAttribute"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵtext(2,"tb.rulenode.reply-routing-configuration"),t.ɵɵelementEnd(),t.ɵɵelement(3,"tb-example-hint",2),t.ɵɵelementStart(4,"div",3)(5,"mat-form-field",4)(6,"mat-label",5),t.ɵɵtext(7,"tb.rulenode.service-id-metadata-attribute"),t.ɵɵelementEnd(),t.ɵɵelement(8,"input",6),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"mat-form-field",4)(10,"mat-label",5),t.ɵɵtext(11,"tb.rulenode.request-id-metadata-attribute"),t.ɵɵelementEnd(),t.ɵɵelement(12,"input",7),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.sendRestApiCallReplyConfigForm),t.ɵɵadvance(3),t.ɵɵproperty("hintText","tb.rulenode.reply-routing-configuration-hint"))},dependencies:t.ɵɵgetComponentDepsFactory(fr),encapsulation:2})}}e("SendRestApiCallReplyConfigComponent",fr);const gr=["attributeChipList"],hr=()=>({standalone:!0});function yr(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",21),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.telemetryTypeTranslationsMap.get(e))," ")}}function br(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"mat-chip-row",22),t.ɵɵlistener("removed",(function(){const n=t.ɵɵrestoreView(e).$implicit,r=t.ɵɵnextContext();return t.ɵɵresetView(r.removeKey(n))})),t.ɵɵtext(1),t.ɵɵelementStart(2,"mat-icon",23),t.ɵɵtext(3,"close"),t.ɵɵelementEnd()()}if(2&e){const e=n.$implicit;t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e," ")}}function vr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(2,1,"tb.rulenode.attributes-keys-required")))}function xr(e,n){1&e&&(t.ɵɵelementStart(0,"div",18),t.ɵɵpipe(1,"translate"),t.ɵɵelementStart(2,"mat-slide-toggle",24),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(1,2,"tb.rulenode.notify-device-on-delete-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(4,4,"tb.rulenode.notify-device")," "))}class Cr extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.attributeScopeMap=o,this.attributeScopes=Object.keys(o),this.telemetryTypeTranslationsMap=l,this.separatorKeysCodes=[U,H,z]}configForm(){return this.deleteAttributesConfigForm}onConfigurationSet(e){this.deleteAttributesConfigForm=this.fb.group({scope:[e?e.scope:null,[N.required]],keys:[e?e.keys:null,[N.required]],sendAttributesDeletedNotification:[!!e&&e.sendAttributesDeletedNotification,[]],notifyDevice:[!!e&&e.notifyDevice,[]]}),this.deleteAttributesConfigForm.get("scope").valueChanges.subscribe((e=>{e!==o.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="")}static{this.ɵfac=function(e){return new(e||Cr)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Cr,selectors:[["tb-action-node-delete-attributes-config"]],viewQuery:function(e,n){if(1&e&&t.ɵɵviewQuery(gr,5),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.attributeChipList=e.first)}},features:[t.ɵɵInheritDefinitionFeature],decls:41,vars:31,consts:[["attributeChipList",""],[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],[1,"tb-form-panel","stroked"],[3,"hintText"],[1,"tb-form-row","no-border","no-padding","tb-standard-fields"],[1,"flex"],["required","","matInput","","formControlName","scope",1,"tb-entity-type-select"],[3,"value",4,"ngFor","ngForOf"],["type","text","matInput","","readonly","","disabled","",3,"ngModel","ngModelOptions"],["type","button","matSuffix","","mat-icon-button","","aria-label","Copy","ngxClipboard","",3,"cbContent","matTooltip"],["aria-hidden","false","aria-label","help-icon"],["subscriptSizing","dynamic",1,"mat-block"],["formControlName","keys"],[3,"removed",4,"ngFor","ngForOf"],["matInput","","type","text",3,"matChipInputTokenEnd","matChipInputFor","matChipInputSeparatorKeyCodes","matChipInputAddOnBlur"],[4,"ngIf"],["translate",""],[1,"tb-settings"],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","sendAttributesDeletedNotification",1,"mat-slide"],["class","tb-form-row no-border no-padding",3,"tb-hint-tooltip-icon",4,"ngIf"],[3,"value"],[3,"removed"],["matChipRemove",""],["formControlName","notifyDevice",1,"mat-slide"]],template:function(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"section",1)(1,"div",2),t.ɵɵelement(2,"tb-example-hint",3),t.ɵɵelementStart(3,"div",4)(4,"mat-form-field",5)(5,"mat-label"),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-select",6),t.ɵɵtemplate(9,yr,3,4,"mat-option",7),t.ɵɵelementEnd()(),t.ɵɵelementStart(10,"mat-form-field",5)(11,"mat-label"),t.ɵɵtext(12),t.ɵɵpipe(13,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(14,"input",8),t.ɵɵelementStart(15,"button",9),t.ɵɵpipe(16,"translate"),t.ɵɵelementStart(17,"mat-icon",10),t.ɵɵtext(18,"content_copy "),t.ɵɵelementEnd()()()()(),t.ɵɵelementStart(19,"mat-form-field",11)(20,"mat-label"),t.ɵɵtext(21),t.ɵɵpipe(22,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(23,"mat-chip-grid",12,0),t.ɵɵtemplate(25,br,4,1,"mat-chip-row",13),t.ɵɵelementStart(26,"input",14),t.ɵɵlistener("matChipInputTokenEnd",(function(r){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.addKey(r))})),t.ɵɵelementEnd()(),t.ɵɵtemplate(27,vr,3,3,"mat-error",15),t.ɵɵelementStart(28,"mat-hint",16),t.ɵɵtext(29,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(30,"section",2)(31,"mat-expansion-panel",17)(32,"mat-expansion-panel-header")(33,"mat-panel-title",16),t.ɵɵtext(34,"tb.rulenode.advanced-settings"),t.ɵɵelementEnd()(),t.ɵɵelementStart(35,"div",18),t.ɵɵpipe(36,"translate"),t.ɵɵelementStart(37,"mat-slide-toggle",19),t.ɵɵtext(38),t.ɵɵpipe(39,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(40,xr,5,6,"div",20),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵreference(24);t.ɵɵproperty("formGroup",n.deleteAttributesConfigForm),t.ɵɵadvance(2),t.ɵɵproperty("hintText","tb.rulenode.attributes-scope-hint"),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(7,18,"tb.rulenode.attributes-scope")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.attributeScopes),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(13,20,"tb.rulenode.attributes-scope-value")),t.ɵɵadvance(2),t.ɵɵproperty("ngModel",n.deleteAttributesConfigForm.get("scope").value)("ngModelOptions",t.ɵɵpureFunction0(30,hr)),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(16,22,"tb.rulenode.attributes-scope-value-copy")),t.ɵɵproperty("cbContent",n.deleteAttributesConfigForm.get("scope").value),t.ɵɵadvance(6),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(22,24,"tb.rulenode.attributes-keys")),t.ɵɵadvance(4),t.ɵɵproperty("ngForOf",n.deleteAttributesConfigForm.get("keys").value),t.ɵɵadvance(),t.ɵɵproperty("matChipInputFor",e)("matChipInputSeparatorKeyCodes",n.separatorKeysCodes)("matChipInputAddOnBlur",!0),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.deleteAttributesConfigForm.get("keys").hasError("required")),t.ɵɵadvance(8),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(36,26,"tb.rulenode.send-attributes-deleted-notification-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(39,28,"tb.rulenode.send-attributes-deleted-notification")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.deleteAttributesConfigForm.get("scope").value===n.attributeScopeMap.SHARED_SCOPE)}},dependencies:t.ɵɵgetComponentDepsFactory(Cr),encapsulation:2})}}e("DeleteAttributesConfigComponent",Cr);const Sr=(e,t)=>[e,t];function Tr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error",8),t.ɵɵtext(1," tb.rulenode.custom-expression-field-input-required "),t.ɵɵelementEnd())}function Ir(e,n){if(1&e&&(t.ɵɵelementStart(0,"fieldset",2)(1,"legend",21),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"mat-form-field",22),t.ɵɵelement(5,"input",23),t.ɵɵtemplate(6,Tr,2,0,"mat-error",11),t.ɵɵelementStart(7,"mat-hint",8),t.ɵɵtext(8,"tb.rulenode.custom-expression-field-input-hint"),t.ɵɵelementEnd()()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵtextInterpolate1("",t.ɵɵpipeBind1(3,2,"tb.rulenode.custom-expression-field-input")," *"),t.ɵɵadvance(4),t.ɵɵproperty("ngIf",e.mathFunctionConfigForm.get("customFunction").hasError("required"))}}function Er(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",24),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementStart(3,"small",25),t.ɵɵtext(4),t.ɵɵelementEnd()()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,3,r.argumentTypeResultMap.get(e).name)," "),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",r.argumentTypeResultMap.get(e).description," ")}}function Fr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error",8),t.ɵɵtext(1," tb.rulenode.type-field-input-required "),t.ɵɵelementEnd())}function qr(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",28),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.attributeScopeMap.get(e))," ")}}function Ar(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",7)(1,"mat-label",8),t.ɵɵtext(2,"tb.rulenode.attribute-scope-field-input"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"mat-select",26),t.ɵɵtemplate(4,qr,3,4,"mat-option",27),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵproperty("ngForOf",e.attributeScopeResult)}}function kr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error",8),t.ɵɵtext(1," tb.rulenode.key-field-input-required "),t.ɵɵelementEnd())}function Nr(e,n){1&e&&(t.ɵɵelementStart(0,"div",29)(1,"mat-checkbox",30),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"mat-checkbox",31),t.ɵɵtext(5),t.ɵɵpipe(6,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(3,2,"tb.rulenode.add-to-message-field-input")," "),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(6,4,"tb.rulenode.add-to-metadata-field-input")," "))}class wr extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.MathFunction=Rt,this.ArgumentTypeResult=Gt,this.argumentTypeResultMap=Qt,this.attributeScopeMap=Xt,this.argumentsResult=Object.values(Gt),this.attributeScopeResult=Object.values(Wt)}configForm(){return this.mathFunctionConfigForm}onConfigurationSet(e){this.mathFunctionConfigForm=this.fb.group({operation:[e?e.operation:null,[N.required]],arguments:[e?e.arguments:null,[N.required]],customFunction:[e?e.customFunction:"",[N.required]],result:this.fb.group({type:[e?e.result.type:null,[N.required]],attributeScope:[e?e.result.attributeScope:null,[N.required]],key:[e?e.result.key:"",[N.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===Rt.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===Gt.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"]}static{this.ɵfac=function(e){return new(e||wr)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:wr,selectors:[["tb-action-node-math-function-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:39,vars:23,consts:[[1,"flex","flex-col",3,"formGroup"],["required","","formControlName","operation",1,"flex-full","max-h-30%","xs:max-h-full","md:max-h-full"],[1,"fields-group","flex","flex-col","gap-2"],["translate","",1,"group-title"],["formControlName","arguments",3,"function"],["class","fields-group flex flex-col gap-2",4,"ngIf"],["formGroupName","result"],[1,"mat-block","flex-1"],["translate",""],["formControlName","type","required",""],["style","border-bottom: 1px solid #eee;",3,"value",4,"ngFor","ngForOf"],["translate","",4,"ngIf"],[1,"xs:flex-col","gt-xs:gap-4","flex","flex-1","flex-row"],["class","mat-block flex-1",4,"ngIf"],["floatLabel","always",1,"mat-block","flex-1"],["matInput","","formControlName","key","required",""],["aria-hidden","false","aria-label","help-icon","matSuffix","","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],["floatLabel","always","subscriptSizing","dynamic",1,"mat-block","flex-1"],["formControlName","resultValuePrecision","matInput","","step","1","min","0","type","number"],[3,"innerHTML"],["class","xs:flex-col gt-xs:gap-4 flex flex-1 flex-row items-stretch justify-start","style","padding-top: 16px;",4,"ngIf"],[1,"group-title"],["subscriptSizing","dynamic",1,"mat-block","no-margin-top","flex-1"],["matInput","","formControlName","customFunction","required",""],[2,"border-bottom","1px solid #eee",3,"value"],[2,"display","block","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],["required","","formControlName","attributeScope"],[3,"value",4,"ngFor","ngForOf"],[3,"value"],[1,"xs:flex-col","gt-xs:gap-4","flex","flex-1","flex-row","items-stretch","justify-start",2,"padding-top","16px"],["formControlName","addToBody"],["formControlName","addToMetadata"]],template:function(e,n){if(1&e&&(t.ɵɵelementStart(0,"section",0),t.ɵɵelement(1,"tb-math-function-autocomplete",1),t.ɵɵelementStart(2,"fieldset",2)(3,"legend",3),t.ɵɵtext(4,"tb.rulenode.argument-tile"),t.ɵɵelementEnd(),t.ɵɵelement(5,"tb-arguments-map-config",4),t.ɵɵelementEnd(),t.ɵɵtemplate(6,Ir,9,4,"fieldset",5),t.ɵɵelementStart(7,"fieldset",2)(8,"legend",3),t.ɵɵtext(9,"tb.rulenode.result-title"),t.ɵɵelementEnd(),t.ɵɵelementStart(10,"div",6)(11,"mat-form-field",7)(12,"mat-label",8),t.ɵɵtext(13,"tb.rulenode.type-field-input"),t.ɵɵelementEnd(),t.ɵɵelementStart(14,"mat-select",9)(15,"mat-select-trigger"),t.ɵɵtext(16),t.ɵɵpipe(17,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(18,Er,5,5,"mat-option",10),t.ɵɵelementEnd(),t.ɵɵtemplate(19,Fr,2,0,"mat-error",11),t.ɵɵelementEnd(),t.ɵɵelementStart(20,"div",12),t.ɵɵtemplate(21,Ar,5,1,"mat-form-field",13),t.ɵɵelementStart(22,"mat-form-field",14)(23,"mat-label",8),t.ɵɵtext(24,"tb.rulenode.key-field-input"),t.ɵɵelementEnd(),t.ɵɵelement(25,"input",15),t.ɵɵelementStart(26,"mat-icon",16),t.ɵɵpipe(27,"translate"),t.ɵɵtext(28,"help"),t.ɵɵelementEnd(),t.ɵɵtemplate(29,kr,2,0,"mat-error",11),t.ɵɵelementEnd()(),t.ɵɵelementStart(30,"div",12)(31,"mat-form-field",17)(32,"mat-label",8),t.ɵɵtext(33,"tb.rulenode.number-floating-point-field-input"),t.ɵɵelementEnd(),t.ɵɵelement(34,"input",18)(35,"mat-hint",19),t.ɵɵpipe(36,"translate"),t.ɵɵpipe(37,"safe"),t.ɵɵelementEnd()(),t.ɵɵtemplate(38,Nr,7,6,"div",20),t.ɵɵelementEnd()()()),2&e){let e;t.ɵɵproperty("formGroup",n.mathFunctionConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("function",n.mathFunctionConfigForm.get("operation").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.mathFunctionConfigForm.get("operation").value===n.MathFunction.CUSTOM),t.ɵɵadvance(10),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(17,11,null==(e=n.argumentTypeResultMap.get(n.mathFunctionConfigForm.get("result.type").value))?null:e.name)," "),t.ɵɵadvance(2),t.ɵɵproperty("ngForOf",n.argumentsResult),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.mathFunctionConfigForm.get("result.type").hasError("required")),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.mathFunctionConfigForm.get("result").get("type").value===n.ArgumentTypeResult.ATTRIBUTE),t.ɵɵadvance(5),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(27,13,"tb.rulenode.math-templatization-tooltip")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.mathFunctionConfigForm.get("result.key").hasError("required")),t.ɵɵadvance(6),t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(37,17,t.ɵɵpipeBind1(36,15,"tb.rulenode.number-floating-point-field-input-hint"),"html"),t.ɵɵsanitizeHtml),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",t.ɵɵpureFunction2(20,Sr,n.ArgumentTypeResult.ATTRIBUTE,n.ArgumentTypeResult.TIME_SERIES).includes(n.mathFunctionConfigForm.get("result").get("type").value))}},dependencies:t.ɵɵgetComponentDepsFactory(wr),styles:["[_nghost-%COMP%] .fields-group{padding:0 16px 8px;margin:10px 0;border:1px groove rgba(0,0,0,.25);border-radius:4px}[_nghost-%COMP%] .fields-group .mat-mdc-form-field .mat-mdc-form-field-infix{width:100%}[_nghost-%COMP%] .fields-group legend{color:#000000b3;width:fit-content}[_nghost-%COMP%] .fields-group legend+*{display:block}[_nghost-%COMP%] .fields-group legend+*.no-margin-top{margin-top:0}"]})}}function Mr(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",4),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",r.messageTypeNames.get(e)," ")}}e("MathFunctionConfigComponent",wr);class Br extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.messageTypeNames=f,this.eventOptions=[g.CONNECT_EVENT,g.ACTIVITY_EVENT,g.DISCONNECT_EVENT,g.INACTIVITY_EVENT]}configForm(){return this.deviceState}prepareInputConfig(e){return{event:P(e?.event)?e.event:g.ACTIVITY_EVENT}}onConfigurationSet(e){this.deviceState=this.fb.group({event:[e.event,[N.required]]})}static{this.ɵfac=function(e){return new(e||Br)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Br,selectors:[["tb-action-node-device-state-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:7,vars:5,consts:[[3,"formGroup"],["subscriptSizing","dynamic",1,"mat-block"],["formControlName","event"],[3,"value",4,"ngFor","ngForOf"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label"),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-select",2),t.ɵɵtemplate(6,Mr,2,2,"mat-option",3),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.deviceState),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(4,3,"tb.rulenode.select-device-connectivity-event")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.eventOptions))},dependencies:t.ɵɵgetComponentDepsFactory(Br),encapsulation:2})}}e("DeviceStateConfigComponent",Br);const Vr=(e,t)=>({valText:e,keyText:t});function Or(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",13),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.requiredText," ")}}function Dr(e,n){1&e&&(t.ɵɵelementStart(0,"div",13),t.ɵɵtext(1," tb.rulenode.map-fields-required "),t.ɵɵelementEnd())}function Lr(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",13),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind2(2,1,"tb.key-val.unique-key-value-pair-error",t.ɵɵpureFunction2(4,Vr,e.valText,e.keyText))," ")}}function Pr(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"div",14)(1,"mat-form-field",15),t.ɵɵelement(2,"input",16),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"mat-form-field",15),t.ɵɵelement(4,"input",16),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"div",17)(6,"button",18),t.ɵɵpipe(7,"translate"),t.ɵɵlistener("click",(function(){const n=t.ɵɵrestoreView(e).index,r=t.ɵɵnextContext();return t.ɵɵresetView(r.removeKeyVal(n))})),t.ɵɵelementStart(8,"mat-icon"),t.ɵɵtext(9,"delete"),t.ɵɵelementEnd()()()()}if(2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵproperty("placeholder",r.keyText+"*")("formControl",e.get("key")),t.ɵɵadvance(2),t.ɵɵproperty("placeholder",r.valText+"*")("formControl",e.get("value")),t.ɵɵadvance(2),t.ɵɵclassProp("tb-hidden",1===r.keyValsFormArray().controls.length),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(7,8,"tb.key-val.remove-mapping-entry")),t.ɵɵproperty("disabled",r.disabled)}}function Rr(e,n){if(1&e&&t.ɵɵelement(0,"tb-example-hint",19),2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("hintText",e.hintText)("popupHelpLink",e.popupHelpLink)}}class _r{constructor(e,t){this.injector=e,this.fb=t,this.propagateChange=()=>{},this.destroy$=new Y,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 w||e instanceof M){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 R(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(W(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,[N.required,N.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:[t.value,[N.required,N.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:["",[N.required,N.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],value:["",[N.required,N.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)}}static{this.ɵfac=function(e){return new(e||_r)(t.ɵɵdirectiveInject(t.Injector),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:_r,selectors:[["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"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>_r)),multi:!0},{provide:O,useExisting:r((()=>_r)),multi:!0}])],decls:22,vars:12,consts:[[1,"tb-form-panel","stroked",3,"formGroup"],[1,"tb-form-row","no-padding","no-border","space-between"],[1,"tb-form-panel-title"],["class","tb-form-panel-hint tb-error","translate","",4,"ngIf"],[1,"tb-form-panel","no-border","no-padding"],[1,"tb-form-table"],[1,"tb-form-table-header"],[1,"tb-form-table-header-cell","field-space"],[1,"tb-form-table-header-cell","actions-header"],[1,"tb-form-table-body"],["class","tb-form-table-row",4,"ngFor","ngForOf"],["type","button","mat-stroked-button","","color","primary",3,"click"],[3,"hintText","popupHelpLink",4,"ngIf"],["translate","",1,"tb-form-panel-hint","tb-error"],[1,"tb-form-table-row"],["appearance","outline","subscriptSizing","dynamic",1,"tb-inline-field","field-space"],["matInput","",3,"placeholder","formControl"],[1,"tb-form-table-row-cell-buttons"],["type","button","mat-icon-button","","matTooltipPosition","above",3,"click","disabled","matTooltip"],[3,"hintText","popupHelpLink"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2),t.ɵɵtext(3),t.ɵɵelementEnd(),t.ɵɵtemplate(4,Or,2,1,"div",3)(5,Dr,2,0,"div",3)(6,Lr,3,7,"div",3),t.ɵɵelementEnd(),t.ɵɵelementStart(7,"div",4)(8,"div",5)(9,"div",6)(10,"div",7),t.ɵɵtext(11),t.ɵɵelementEnd(),t.ɵɵelementStart(12,"div",7),t.ɵɵtext(13),t.ɵɵelementEnd(),t.ɵɵelement(14,"div",8),t.ɵɵelementEnd(),t.ɵɵelementStart(15,"div",9),t.ɵɵtemplate(16,Pr,10,10,"div",10),t.ɵɵelementEnd()()(),t.ɵɵelementStart(17,"div")(18,"button",11),t.ɵɵlistener("click",(function(){return n.addKeyVal()})),t.ɵɵtext(19),t.ɵɵpipe(20,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(21,Rr,1,2,"tb-example-hint",12),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.kvListFormGroup),t.ɵɵadvance(3),t.ɵɵtextInterpolate(n.labelText),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.kvListFormGroup.hasError("kvMapRequired")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.kvListFormGroup.hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.kvListFormGroup.hasError("uniqueKeyValuePair")),t.ɵɵadvance(5),t.ɵɵtextInterpolate(n.keyText),t.ɵɵadvance(2),t.ɵɵtextInterpolate(n.valText),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.keyValsFormArray().controls),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(20,10,"tb.key-val.add-mapping-entry")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.popupHelpLink||n.hintText))},dependencies:t.ɵɵgetComponentDepsFactory(_r),styles:["[_nghost-%COMP%] .field-space[_ngcontent-%COMP%]{flex:1 1 50%}[_nghost-%COMP%] .actions-header[_ngcontent-%COMP%]{width:40px}"]})}}e("KvMapConfigComponent",_r),J([h()],_r.prototype,"disabled",void 0),J([h()],_r.prototype,"uniqueKeyValuePairValidator",void 0),J([h()],_r.prototype,"required",void 0);const jr=e=>({inputName:e});function Gr(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",13),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementStart(3,"span",3),t.ɵɵtext(4,"tb.rulenode.relations-query-config-direction-suffix"),t.ɵɵelementEnd()()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.directionTypeTranslations.get(e))," ")}}function Kr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-relation-level-error")," "))}function Ur(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-relation-level-invalid")," "))}function Hr(e,n){1&e&&(t.ɵɵelementStart(0,"div",14),t.ɵɵpipe(1,"translate"),t.ɵɵelementStart(2,"mat-slide-toggle",15),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(1,2,"tb.rulenode.last-level-device-relation-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(4,4,"alias.last-level-relation")," "))}class zr extends y{get required(){return this.requiredValue}set required(e){this.requiredValue=Z(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(d),this.directionTypeTranslations=b,this.entityType=u,this.propagateChange=null}ngOnInit(){this.deviceRelationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[N.required]],maxLevel:[null,[N.min(1)]],relationType:[null],deviceTypes:[null,[N.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})}static{this.ɵfac=function(e){return new(e||zr)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:zr,selectors:[["tb-device-relations-query-config"]],inputs:{disabled:"disabled",required:"required"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>zr)),multi:!0}]),t.ɵɵInheritDefinitionFeature],decls:24,vars:26,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"flex","flex-row","gap-5.5"],["subscriptSizing","dynamic","hideRequiredMarker","",1,"mat-block","max-w-50%","flex-full",2,"min-width","100px"],["translate",""],["required","","formControlName","direction"],[3,"value",4,"ngFor","ngForOf"],["floatLabel","always",1,"mat-block","max-w-50%","flex-full"],["matInput","","type","text","pattern","[0-9]*","inputmode","numeric","min","1","formControlName","maxLevel",3,"placeholder"],[4,"ngIf"],["class","tb-form-row no-border no-padding last-level-slide-toggle",3,"tb-hint-tooltip-icon",4,"ngIf"],["formControlName","relationType",1,"flex-1"],["required","","formControlName","deviceTypes",3,"label","entityType","emptyInputPlaceholder","filledInputPlaceholder"],["matSuffix","","aria-hidden","false","aria-label","help-icon","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],[3,"value"],[1,"tb-form-row","no-border","no-padding","last-level-slide-toggle",3,"tb-hint-tooltip-icon"],["formControlName","fetchLastLevelOnly",1,"mat-slide"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"mat-form-field",2)(3,"mat-label",3),t.ɵɵtext(4,"relation.direction"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-select",4),t.ɵɵtemplate(6,Gr,5,4,"mat-option",5),t.ɵɵelementEnd()(),t.ɵɵelementStart(7,"mat-form-field",6)(8,"mat-label",3),t.ɵɵtext(9,"tb.rulenode.max-relation-level"),t.ɵɵelementEnd(),t.ɵɵelement(10,"input",7),t.ɵɵpipe(11,"translate"),t.ɵɵtemplate(12,Kr,3,3,"mat-error",8)(13,Ur,3,3,"mat-error",8),t.ɵɵelementEnd()(),t.ɵɵtemplate(14,Hr,5,6,"div",9),t.ɵɵelement(15,"tb-relation-type-autocomplete",10),t.ɵɵelementStart(16,"tb-entity-subtype-list",11),t.ɵɵpipe(17,"translate"),t.ɵɵpipe(18,"translate"),t.ɵɵpipe(19,"translate"),t.ɵɵelementStart(20,"mat-icon",12),t.ɵɵpipe(21,"translate"),t.ɵɵpipe(22,"translate"),t.ɵɵtext(23,"help"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.deviceRelationsQueryFormGroup),t.ɵɵadvance(6),t.ɵɵproperty("ngForOf",n.directionTypes),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("placeholder",t.ɵɵpipeBind1(11,11,"tb.rulenode.unlimited-level")),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.deviceRelationsQueryFormGroup.get("maxLevel").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.deviceRelationsQueryFormGroup.get("maxLevel").invalid),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.deviceRelationsQueryFormGroup.get("maxLevel").value>1),t.ɵɵadvance(2),t.ɵɵproperty("label",t.ɵɵpipeBind1(17,13,"tb.rulenode.device-profiles"))("entityType",n.entityType.DEVICE)("emptyInputPlaceholder",t.ɵɵpipeBind1(18,15,"tb.rulenode.add-device-profile"))("filledInputPlaceholder",t.ɵɵpipeBind1(19,17,"tb.rulenode.add-device-profile")),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind2(22,21,"tb.rulenode.chip-help",t.ɵɵpureFunction1(24,jr,t.ɵɵpipeBind1(21,19,"tb.rulenode.device-profile")))))},dependencies:t.ɵɵgetComponentDepsFactory(zr),styles:["[_nghost-%COMP%] .last-level-slide-toggle[_ngcontent-%COMP%]{margin:8px 0 24px}"]})}}function $r(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",13),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementStart(3,"span",4),t.ɵɵtext(4,"tb.rulenode.relations-query-config-direction-suffix"),t.ɵɵelementEnd()()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.directionTypeTranslations.get(e))," ")}}function Qr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-relation-level-error")," "))}function Jr(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-relation-level-invalid")," "))}function Yr(e,n){1&e&&(t.ɵɵelementStart(0,"div",14),t.ɵɵpipe(1,"translate"),t.ɵɵelementStart(2,"mat-slide-toggle",15),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(1,2,"tb.rulenode.last-level-relation-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(4,4,"alias.last-level-relation")," "))}e("DeviceRelationsQueryConfigComponent",zr);class Wr extends y{get required(){return this.requiredValue}set required(e){this.requiredValue=Z(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.values(d),this.directionTypeTranslations=b,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[N.required]],maxLevel:[null,[N.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})}static{this.ɵfac=function(e){return new(e||Wr)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Wr,selectors:[["tb-relations-query-config"]],inputs:{disabled:"disabled",required:"required"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>Wr)),multi:!0}]),t.ɵɵInheritDefinitionFeature],decls:22,vars:9,consts:[[1,"tb-form-panel","stroked",3,"formGroup"],["translate","",1,"tb-form-panel-title","tb-required"],[1,"flex","flex-row","gap-4"],["hideRequiredMarker","",1,"mat-block","max-w-50%","flex-full",2,"min-width","100px"],["translate",""],["required","","formControlName","direction"],[3,"value",4,"ngFor","ngForOf"],["floatLabel","always",1,"mat-block","max-w-50%","flex-full"],["matInput","","type","text","pattern","[0-9]*","min","1","inputmode","numeric","formControlName","maxLevel",3,"placeholder"],[4,"ngIf"],["class","tb-form-row no-border no-padding last-level-slide-toggle",3,"tb-hint-tooltip-icon",4,"ngIf"],["translate","",1,"tb-form-panel-title"],["formControlName","filters"],[3,"value"],[1,"tb-form-row","no-border","no-padding","last-level-slide-toggle",3,"tb-hint-tooltip-icon"],["formControlName","fetchLastLevelOnly",1,"mat-slide"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵtext(2,"tb.rulenode.relations-query"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"section")(4,"div",2)(5,"mat-form-field",3)(6,"mat-label",4),t.ɵɵtext(7,"relation.direction"),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-select",5),t.ɵɵtemplate(9,$r,5,4,"mat-option",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(10,"mat-form-field",7)(11,"mat-label",4),t.ɵɵtext(12,"tb.rulenode.max-relation-level"),t.ɵɵelementEnd(),t.ɵɵelement(13,"input",8),t.ɵɵpipe(14,"translate"),t.ɵɵtemplate(15,Qr,3,3,"mat-error",9)(16,Jr,3,3,"mat-error",9),t.ɵɵelementEnd()(),t.ɵɵtemplate(17,Yr,5,6,"div",10),t.ɵɵelementEnd(),t.ɵɵelementStart(18,"section",0)(19,"div",11),t.ɵɵtext(20,"relation.relation-filters"),t.ɵɵelementEnd(),t.ɵɵelement(21,"tb-relation-filters",12),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.relationsQueryFormGroup),t.ɵɵadvance(9),t.ɵɵproperty("ngForOf",n.directionTypes),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("placeholder",t.ɵɵpipeBind1(14,7,"tb.rulenode.unlimited-level")),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.relationsQueryFormGroup.get("maxLevel").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.relationsQueryFormGroup.get("maxLevel").invalid),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.relationsQueryFormGroup.get("maxLevel").value>1),t.ɵɵadvance(),t.ɵɵproperty("formGroup",n.relationsQueryFormGroup))},dependencies:t.ɵɵgetComponentDepsFactory(Wr),encapsulation:2})}}e("RelationsQueryConfigComponent",Wr);const Xr=["chipList"],Zr=["messageTypeAutocomplete"],ea=["messageTypeInput"],ta=e=>({inputName:e}),na=e=>({messageType:e});function ra(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-label"),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵtextInterpolate(e.label)}}function aa(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"mat-chip-row",13),t.ɵɵlistener("removed",(function(){const n=t.ɵɵrestoreView(e).$implicit,r=t.ɵɵnextContext();return t.ɵɵresetView(r.remove(n))})),t.ɵɵtext(1),t.ɵɵelementStart(2,"mat-icon",14),t.ɵɵtext(3,"close"),t.ɵɵelementEnd()()}if(2&e){const e=n.$implicit;t.ɵɵproperty("removable",!0),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.name," ")}}function ia(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",15),t.ɵɵelement(1,"span",16),t.ɵɵpipe(2,"highlight"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(2,2,e.name,r.searchText),t.ɵɵsanitizeHtml)}}function oa(e,n){1&e&&(t.ɵɵelementStart(0,"div")(1,"span",21),t.ɵɵtext(2,"tb.rulenode.no-message-types-found"),t.ɵɵelementEnd()())}function la(e,n){if(1&e&&(t.ɵɵelementStart(0,"span"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind2(2,1,"tb.rulenode.no-message-type-matching",t.ɵɵpureFunction1(4,na,e.truncate.transform(e.searchText,!0,6,"...")))," ")}}function sa(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"mat-option",17)(1,"div",18),t.ɵɵlistener("click",(function(n){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.stopPropagation())})),t.ɵɵtemplate(2,oa,3,0,"div",19)(3,la,3,6,"ng-template",null,3,t.ɵɵtemplateRefExtractor),t.ɵɵelementStart(5,"span")(6,"a",20),t.ɵɵlistener("click",(function(n){t.ɵɵrestoreView(e);const r=t.ɵɵnextContext();return t.ɵɵresetView(r.createMessageType(n,r.searchText))})),t.ɵɵtext(7,"tb.rulenode.create-new-message-type"),t.ɵɵelementEnd()()()()}if(2&e){const e=t.ɵɵreference(4),n=t.ɵɵnextContext();t.ɵɵproperty("value",null),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!n.textIsNotEmpty(n.searchText))("ngIfElse",e)}}function pa(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.select-message-types-required")," "))}class ma extends y{get required(){return this.requiredValue}set required(e){this.requiredValue=Z(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=[U,H,z],this.messageTypes=[],this.messageTypesList=[],this.searchText="",this.propagateChange=e=>{},this.messageTypeConfigForm=this.fb.group({messageType:[null]});for(const e of Object.keys(g))this.messageTypesList.push({name:f.get(g[e]),value:e})}registerOnChange(e){this.propagateChange=e}registerOnTouched(e){}ngOnInit(){this.filteredMessageTypes=this.messageTypeConfigForm.get("messageType").valueChanges.pipe(ee(""),te((e=>e||"")),ne((e=>this.fetchMessageTypes(e))),re())}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 X(this.messageTypesList.filter((t=>t.name.toUpperCase().includes(e))))}return X(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))}static{this.ɵfac=function(e){return new(e||ma)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(v.TruncatePipe),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:ma,selectors:[["tb-message-types-config"]],viewQuery:function(e,n){if(1&e&&(t.ɵɵviewQuery(Xr,5),t.ɵɵviewQuery(Zr,5),t.ɵɵviewQuery(ea,5)),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.chipList=e.first),t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.matAutocomplete=e.first),t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.messageTypeInput=e.first)}},inputs:{required:"required",label:"label",placeholder:"placeholder",disabled:"disabled"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>ma)),multi:!0}]),t.ɵɵInheritDefinitionFeature],decls:20,vars:27,consts:[["chipList",""],["messageTypeInput","","origin","matAutocompleteOrigin"],["messageTypeAutocomplete","matAutocomplete"],["searchNotEmpty",""],[2,"width","100%",3,"formGroup"],[4,"ngIf"],[3,"required"],[3,"removable","removed",4,"ngFor","ngForOf"],["matInput","","type","text","formControlName","messageType","matAutocompleteOrigin","",3,"focusin","matChipInputTokenEnd","placeholder","matAutocompleteConnectedTo","matAutocomplete","matChipInputFor","matChipInputSeparatorKeyCodes"],[1,"tb-autocomplete",3,"optionSelected","displayWith"],[3,"value",4,"ngFor","ngForOf"],["class","tb-not-found",3,"value",4,"ngIf"],["aria-hidden","false","aria-label","help-icon","matSuffix","","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],[3,"removed","removable"],["matChipRemove",""],[3,"value"],[3,"innerHTML"],[1,"tb-not-found",3,"value"],[1,"tb-not-found-content",3,"click"],[4,"ngIf","ngIfElse"],["translate","",3,"click"],["translate",""]],template:function(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"mat-form-field",4),t.ɵɵtemplate(1,ra,2,1,"mat-label",5),t.ɵɵelementStart(2,"mat-chip-grid",6,0),t.ɵɵtemplate(4,aa,4,2,"mat-chip-row",7),t.ɵɵelementStart(5,"input",8,1),t.ɵɵpipe(8,"translate"),t.ɵɵlistener("focusin",(function(){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.onFocus())}))("matChipInputTokenEnd",(function(r){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.add(r))})),t.ɵɵelementEnd()(),t.ɵɵelementStart(9,"mat-autocomplete",9,2),t.ɵɵlistener("optionSelected",(function(r){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.selected(r))})),t.ɵɵtemplate(11,ia,3,5,"mat-option",10),t.ɵɵpipe(12,"async"),t.ɵɵtemplate(13,sa,8,3,"mat-option",11),t.ɵɵpipe(14,"async"),t.ɵɵelementEnd(),t.ɵɵelementStart(15,"mat-icon",12),t.ɵɵpipe(16,"translate"),t.ɵɵpipe(17,"translate"),t.ɵɵtext(18,"help"),t.ɵɵelementEnd(),t.ɵɵtemplate(19,pa,3,3,"mat-error",5),t.ɵɵelementEnd()}if(2&e){let e;const r=t.ɵɵreference(3),a=t.ɵɵreference(7),i=t.ɵɵreference(10);t.ɵɵproperty("formGroup",n.messageTypeConfigForm),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.label),t.ɵɵadvance(),t.ɵɵproperty("required",n.required),t.ɵɵadvance(2),t.ɵɵproperty("ngForOf",n.messageTypes),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("placeholder",t.ɵɵpipeBind1(8,14,n.placeholder)),t.ɵɵproperty("matAutocompleteConnectedTo",a)("matAutocomplete",i)("matChipInputFor",r)("matChipInputSeparatorKeyCodes",n.separatorKeysCodes),t.ɵɵadvance(4),t.ɵɵproperty("displayWith",n.displayMessageTypeFn),t.ɵɵadvance(2),t.ɵɵproperty("ngForOf",t.ɵɵpipeBind1(12,16,n.filteredMessageTypes)),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",0===(null==(e=t.ɵɵpipeBind1(14,18,n.filteredMessageTypes))?null:e.length)),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind2(17,22,"tb.rulenode.chip-help",t.ɵɵpureFunction1(25,ta,t.ɵɵpipeBind1(16,20,"tb.rulenode.message-type")))),t.ɵɵadvance(4),t.ɵɵproperty("ngIf",r.errorState)}},dependencies:t.ɵɵgetComponentDepsFactory(ma),encapsulation:2})}}function da(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",12),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e)("disabled","cert.PEM"===e&&r.disableCertPemCredentials),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,3,r.credentialsTypeTranslationsMap.get(e))," ")}}function ua(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.credentials-type-required")," "))}function ca(e,t){}function fa(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.username-required")," "))}function ga(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.password-required")," "))}function ha(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",4)(1,"mat-label",2),t.ɵɵtext(2,"tb.rulenode.username"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",13),t.ɵɵtemplate(4,fa,3,3,"mat-error",7),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-form-field",4)(6,"mat-label",2),t.ɵɵtext(7,"tb.rulenode.password"),t.ɵɵelementEnd(),t.ɵɵelement(8,"input",14)(9,"tb-toggle-password",15),t.ɵɵtemplate(10,ga,3,3,"mat-error",7),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(4),t.ɵɵproperty("ngIf",e.credentialsConfigFormGroup.get("username").hasError("required")),t.ɵɵadvance(4),t.ɵɵproperty("required",e.passwordFieldRequired),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",e.credentialsConfigFormGroup.get("password").hasError("required"))}}function ya(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"div",16),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"tb-file-input",17),t.ɵɵpipe(4,"translate"),t.ɵɵpipe(5,"translate"),t.ɵɵlistener("fileNameChanged",(function(n){t.ɵɵrestoreView(e);const r=t.ɵɵnextContext(2);return t.ɵɵresetView(r.credentialsConfigFormGroup.get("caCertFileName").setValue(n))})),t.ɵɵelementEnd(),t.ɵɵelementStart(6,"tb-file-input",18),t.ɵɵpipe(7,"translate"),t.ɵɵpipe(8,"translate"),t.ɵɵlistener("fileNameChanged",(function(n){t.ɵɵrestoreView(e);const r=t.ɵɵnextContext(2);return t.ɵɵresetView(r.credentialsConfigFormGroup.get("certFileName").setValue(n))})),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"tb-file-input",19),t.ɵɵpipe(10,"translate"),t.ɵɵpipe(11,"translate"),t.ɵɵlistener("fileNameChanged",(function(n){t.ɵɵrestoreView(e);const r=t.ɵɵnextContext(2);return t.ɵɵresetView(r.credentialsConfigFormGroup.get("privateKeyFileName").setValue(n))})),t.ɵɵelementEnd(),t.ɵɵelementStart(12,"mat-form-field",4)(13,"mat-label",2),t.ɵɵtext(14,"tb.rulenode.private-key-password"),t.ɵɵelementEnd(),t.ɵɵelement(15,"input",20)(16,"tb-toggle-password",15),t.ɵɵelementEnd()}if(2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(2,10,"tb.rulenode.credentials-pem-hint")),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("label",t.ɵɵpipeBind1(4,12,"tb.rulenode.ca-cert")),t.ɵɵpropertyInterpolate("dropLabel",t.ɵɵpipeBind1(5,14,"tb.rulenode.drop-file")),t.ɵɵproperty("existingFileName",e.credentialsConfigFormGroup.get("caCertFileName").value),t.ɵɵadvance(3),t.ɵɵpropertyInterpolate("label",t.ɵɵpipeBind1(7,16,"tb.rulenode.cert")),t.ɵɵpropertyInterpolate("dropLabel",t.ɵɵpipeBind1(8,18,"tb.rulenode.drop-file")),t.ɵɵproperty("existingFileName",e.credentialsConfigFormGroup.get("certFileName").value),t.ɵɵadvance(3),t.ɵɵpropertyInterpolate("label",t.ɵɵpipeBind1(10,20,"tb.rulenode.private-key")),t.ɵɵpropertyInterpolate("dropLabel",t.ɵɵpipeBind1(11,22,"tb.rulenode.drop-file")),t.ɵɵproperty("existingFileName",e.credentialsConfigFormGroup.get("privateKeyFileName").value)}}function ba(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",4)(1,"mat-label",2),t.ɵɵtext(2,"tb.rulenode.credentials-type"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"mat-select",5),t.ɵɵtemplate(4,da,3,5,"mat-option",6),t.ɵɵelementEnd(),t.ɵɵtemplate(5,ua,3,3,"mat-error",7),t.ɵɵelementEnd(),t.ɵɵelementStart(6,"section",8),t.ɵɵtemplate(7,ca,0,0,"ng-template",9)(8,ha,11,3,"ng-template",10)(9,ya,17,24,"ng-template",11),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵproperty("ngForOf",e.allCredentialsTypes),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.credentialsConfigFormGroup.get("type").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngSwitch",e.credentialsConfigFormGroup.get("type").value)}}e("MessageTypesConfigComponent",ma);class va extends y{get required(){return this.requiredValue}set required(e){this.requiredValue=Z(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.subscriptions=[],this.disableCertPemCredentials=!1,this.passwordFieldRequired=!0,this.allCredentialsTypes=Mt,this.credentialsTypeTranslationsMap=Bt,this.propagateChange=e=>{}}ngOnInit(){this.credentialsConfigFormGroup=this.fb.group({type:[null,[N.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){P(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([N.required]),this.credentialsConfigFormGroup.get("password").setValidators(this.passwordFieldRequired?[N.required]:[]);break;case"cert.PEM":this.credentialsConfigFormGroup.setValidators([this.requiredFilesSelected(N.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}}}static{this.ɵfac=function(e){return new(e||va)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:va,selectors:[["tb-credentials-config"]],inputs:{required:"required",disableCertPemCredentials:"disableCertPemCredentials",passwordFieldRequired:"passwordFieldRequired"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>va)),multi:!0},{provide:O,useExisting:r((()=>va)),multi:!0}]),t.ɵɵInheritDefinitionFeature,t.ɵɵNgOnChangesFeature],decls:9,vars:4,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"tb-credentials-config-panel-group"],["translate",""],["matExpansionPanelContent",""],[1,"mat-block"],["formControlName","type","required",""],[3,"value","disabled",4,"ngFor","ngForOf"],[4,"ngIf"],[1,"flex","flex-col",3,"ngSwitch"],["ngSwitchCase","anonymous"],["ngSwitchCase","basic"],["ngSwitchCase","cert.PEM"],[3,"value","disabled"],["required","","matInput","","formControlName","username"],["type","password","matInput","","formControlName","password",3,"required"],["matSuffix",""],[1,"tb-hint"],["formControlName","caCert","inputId","caCertSelect","noFileText","tb.rulenode.no-file",3,"fileNameChanged","existingFileName","label","dropLabel"],["formControlName","cert","inputId","CertSelect","noFileText","tb.rulenode.no-file",3,"fileNameChanged","existingFileName","label","dropLabel"],["formControlName","privateKey","inputId","privateKeySelect","noFileText","tb.rulenode.no-file",2,"padding-bottom","8px",3,"fileNameChanged","existingFileName","label","dropLabel"],["type","password","matInput","","formControlName","password"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-expansion-panel",1)(2,"mat-expansion-panel-header")(3,"mat-panel-title",2),t.ɵɵtext(4,"tb.rulenode.credentials"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-panel-description"),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(8,ba,10,3,"ng-template",3),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.credentialsConfigFormGroup),t.ɵɵadvance(6),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(7,2,n.credentialsTypeTranslationsMap.get(n.credentialsConfigFormGroup.get("type").value))," "))},dependencies:t.ɵɵgetComponentDepsFactory(va),encapsulation:2})}}function xa(e,n){1&e&&(t.ɵɵelementStart(0,"button",22),t.ɵɵpipe(1,"translate"),t.ɵɵelementStart(2,"mat-icon"),t.ɵɵtext(3,"drag_handle"),t.ɵɵelementEnd()()),2&e&&t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(1,1,"action.drag"))}function Ca(e,n){if(1&e&&(t.ɵɵelementStart(0,"span",23),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext().$implicit;t.ɵɵadvance(),t.ɵɵtextInterpolate1("",e.get("name").value,".")}}function Sa(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",24),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementStart(3,"small",25),t.ɵɵtext(4),t.ɵɵelementEnd()()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,3,r.argumentTypeMap.get(e).name)," "),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",r.argumentTypeMap.get(e).description," ")}}function Ta(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error",13),t.ɵɵtext(1," tb.rulenode.argument-source-field-input-required "),t.ɵɵelementEnd())}function Ia(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error",13),t.ɵɵtext(1," tb.rulenode.argument-key-field-input-required "),t.ɵɵelementEnd())}function Ea(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",26)(1,"mat-label",13),t.ɵɵtext(2,"tb.rulenode.argument-key-field-input"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",27),t.ɵɵelementStart(4,"mat-icon",28),t.ɵɵpipe(5,"translate"),t.ɵɵtext(6," help "),t.ɵɵelementEnd(),t.ɵɵtemplate(7,Ia,2,0,"mat-error",16),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext().$implicit;t.ɵɵadvance(3),t.ɵɵproperty("formControl",e.get("key")),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(5,3,"tb.rulenode.math-templatization-tooltip")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.get("key").hasError("required"))}}function Fa(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error",13),t.ɵɵtext(1," tb.rulenode.constant-value-field-input-required "),t.ɵɵelementEnd())}function qa(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",29)(1,"mat-label",13),t.ɵɵtext(2,"tb.rulenode.constant-value-field-input"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",30),t.ɵɵtemplate(4,Fa,2,0,"mat-error",16),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext().$implicit;t.ɵɵadvance(3),t.ɵɵproperty("formControl",e.get("key")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.get("key").hasError("required"))}}function Aa(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",26)(1,"mat-label",13),t.ɵɵtext(2,"tb.rulenode.default-value-field-input"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",31),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext().$implicit;t.ɵɵadvance(3),t.ɵɵproperty("formControl",e.get("defaultValue"))}}function ka(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",33),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(3);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.attributeScopeMap.get(e))," ")}}function Na(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error",13),t.ɵɵtext(1," tb.rulenode.attribute-scope-field-input-required "),t.ɵɵelementEnd())}function wa(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",12)(1,"mat-label",13),t.ɵɵtext(2,"tb.rulenode.attribute-scope-field-input"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"mat-select",14),t.ɵɵtemplate(4,ka,3,4,"mat-option",32),t.ɵɵelementEnd(),t.ɵɵtemplate(5,Na,2,0,"mat-error",16),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext().$implicit,n=t.ɵɵnextContext();t.ɵɵadvance(3),t.ɵɵproperty("formControl",e.get("attributeScope")),t.ɵɵadvance(),t.ɵɵproperty("ngForOf",n.attributeScope),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.get("attributeScope").hasError("required"))}}function Ma(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"button",34),t.ɵɵpipe(1,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext().index,r=t.ɵɵnextContext();return t.ɵɵresetView(r.removeArgument(n))})),t.ɵɵelementStart(2,"mat-icon"),t.ɵɵtext(3,"close"),t.ɵɵelementEnd()()}2&e&&t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(1,1,"action.remove"))}function Ba(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-list-item",6)(1,"div",7),t.ɵɵtemplate(2,xa,4,3,"button",8),t.ɵɵelementStart(3,"div",9),t.ɵɵtemplate(4,Ca,2,1,"span",10),t.ɵɵelementStart(5,"div",11)(6,"mat-form-field",12)(7,"mat-label",13),t.ɵɵtext(8,"tb.rulenode.argument-source-field-input"),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"mat-select",14)(10,"mat-select-trigger"),t.ɵɵtext(11),t.ɵɵpipe(12,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(13,Sa,5,5,"mat-option",15),t.ɵɵelementEnd(),t.ɵɵtemplate(14,Ta,2,0,"mat-error",16),t.ɵɵelementEnd(),t.ɵɵelementStart(15,"div",17),t.ɵɵtemplate(16,Ea,8,5,"mat-form-field",18)(17,qa,5,2,"mat-form-field",19)(18,Aa,4,1,"mat-form-field",18),t.ɵɵelementEnd(),t.ɵɵtemplate(19,wa,6,3,"mat-form-field",20),t.ɵɵelementEnd(),t.ɵɵtemplate(20,Ma,4,3,"button",21),t.ɵɵelementEnd()()()),2&e){let e;const r=n.$implicit,a=t.ɵɵnextContext();t.ɵɵproperty("cdkDragDisabled",a.disabled),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!a.disabled),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",a.displayArgumentName),t.ɵɵadvance(5),t.ɵɵproperty("formControl",r.get("type")),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(12,12,null==(e=a.argumentTypeMap.get(r.get("type").value))?null:e.name)," "),t.ɵɵadvance(2),t.ɵɵproperty("ngForOf",a.arguments),t.ɵɵadvance(),t.ɵɵproperty("ngIf",r.get("type").hasError("required")),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",r.get("type").value&&r.get("type").value!==a.ArgumentType.CONSTANT),t.ɵɵadvance(),t.ɵɵproperty("ngIf",r.get("type").value===a.ArgumentType.CONSTANT),t.ɵɵadvance(),t.ɵɵproperty("ngIf",r.get("type").value&&r.get("type").value!==a.ArgumentType.CONSTANT),t.ɵɵadvance(),t.ɵɵproperty("ngIf",r.get("type").value===a.ArgumentType.ATTRIBUTE),t.ɵɵadvance(),t.ɵɵproperty("ngIf",!a.disabled)}}function Va(e,n){1&e&&(t.ɵɵelementStart(0,"div")(1,"span",35),t.ɵɵtext(2,"tb.rulenode.no-arguments-prompt"),t.ɵɵelementEnd()())}e("CredentialsConfigComponent",va);class Oa extends y{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=_t,this.ArgumentType=jt,this.attributeScopeMap=Xt,this.argumentTypeMap=$t,this.arguments=Object.values(jt),this.attributeScope=Object.values(Yt),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===Rt.CUSTOM),this.argumentsFormGroup){for(this.argumentsFormGroup.get("arguments").setValidators([N.minLength(this.minArgs),N.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===jt.ATTRIBUTE?e.get("attributeScope").enable({emitEvent:!1}):e.get("attributeScope").disable({emitEvent:!1}),t&&t!==jt.CONSTANT?e.get("defaultValue").enable({emitEvent:!1}):e.get("defaultValue").disable({emitEvent:!1})}updateArgumentNames(){this.argumentsFormArray.controls.forEach(((e,t)=>{e.get("name").setValue(Jt[t])}))}updateModel(){const e=this.argumentsFormArray.value;e.length&&this.argumentsFormGroup.valid?this.propagateChange(e):this.propagateChange(null)}static{this.ɵfac=function(e){return new(e||Oa)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Oa,selectors:[["tb-arguments-map-config"]],inputs:{disabled:"disabled",function:"function"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>Oa)),multi:!0},{provide:O,useExisting:r((()=>Oa)),multi:!0}]),t.ɵɵInheritDefinitionFeature],decls:10,vars:10,consts:[[1,"flex","flex-col"],[2,"max-height","500px","overflow","auto"],["cdkDropList","","cdkDropListOrientation","vertical",1,"tb-drop-list","arguments-list",3,"cdkDropListDropped","formGroup","cdkDropListDisabled"],["formArrayName","arguments","cdkDrag","","class","tb-argument tb-draggable","style","height: 100%",3,"cdkDragDisabled",4,"ngFor","ngForOf"],[4,"ngIf"],["mat-button","","mat-raised-button","","color","primary","type","button","matTooltipPosition","above",3,"click","disabled"],["formArrayName","arguments","cdkDrag","",1,"tb-argument","tb-draggable",2,"height","100%",3,"cdkDragDisabled"],[1,"flex","flex-1","flex-row","items-center","justify-start"],["mat-icon-button","","color","primary","cdkDragHandle","","class","tb-drag-handle handle","style","min-width: 40px; margin: 0","matTooltipPosition","above",3,"matTooltip",4,"ngIf"],[1,"flex","flex-1","flex-row","items-center","justify-start","gap-4"],["style","padding: 0 10px; min-width: 20px;",4,"ngIf"],[1,"flex","flex-1","flex-col"],[1,"mat-block"],["translate",""],["required","",3,"formControl"],["style","border-bottom: 1px solid #eee;",3,"value",4,"ngFor","ngForOf"],["translate","",4,"ngIf"],[1,"flex","flex-1","flex-row","xs:flex-col","gt-xs:gap-4"],["floatLabel","always","class","mat-block gt-xs:max-w-50% gt-xs:flex-full",4,"ngIf"],["floatLabel","always","class","mat-block flex-1",4,"ngIf"],["class","mat-block",4,"ngIf"],["mat-icon-button","","color","primary","style","min-width: 40px;","matTooltipPosition","above",3,"matTooltip","click",4,"ngIf"],["mat-icon-button","","color","primary","cdkDragHandle","","matTooltipPosition","above",1,"tb-drag-handle","handle",2,"min-width","40px","margin","0",3,"matTooltip"],[2,"padding","0 10px","min-width","20px"],[2,"border-bottom","1px solid #eee",3,"value"],[2,"display","block","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"],["floatLabel","always",1,"mat-block","gt-xs:max-w-50%","gt-xs:flex-full"],["matInput","","required","",3,"formControl"],["aria-hidden","false","aria-label","help-icon","matSuffix","","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],["floatLabel","always",1,"mat-block","flex-1"],["matInput","","required","","step","1","min","0","type","number",3,"formControl"],["matInput","","step","1","type","number",3,"formControl"],[3,"value",4,"ngFor","ngForOf"],[3,"value"],["mat-icon-button","","color","primary","matTooltipPosition","above",2,"min-width","40px",3,"click","matTooltip"],["translate","",1,"tb-prompt","flex","items-center","justify-center"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"mat-list",2),t.ɵɵlistener("cdkDropListDropped",(function(e){return n.onDrop(e)})),t.ɵɵtemplate(3,Ba,21,14,"mat-list-item",3),t.ɵɵelementEnd()(),t.ɵɵtemplate(4,Va,3,0,"div",4),t.ɵɵelementStart(5,"button",5),t.ɵɵlistener("click",(function(){return n.addArgument()})),t.ɵɵelementStart(6,"mat-icon"),t.ɵɵtext(7,"add"),t.ɵɵelementEnd(),t.ɵɵtext(8),t.ɵɵpipe(9,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵadvance(),t.ɵɵclassProp("readonly",n.disabled),t.ɵɵadvance(),t.ɵɵproperty("formGroup",n.argumentsFormGroup)("cdkDropListDisabled",n.disabled),t.ɵɵadvance(),t.ɵɵproperty("ngForOf",n.argumentsFormArray.controls),t.ɵɵadvance(),t.ɵɵproperty("ngIf",!n.argumentsFormArray.length),t.ɵɵadvance(),t.ɵɵproperty("disabled",n.argumentsFormArray.length>=n.maxArgs),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(9,8,"action.add")," "))},dependencies:t.ɵɵgetComponentDepsFactory(Oa),styles:["[_nghost-%COMP%] .mat-mdc-list-item.tb-argument[_ngcontent-%COMP%]{border:solid rgba(0,0,0,.25) 1px;border-radius:4px;padding:10px 0;margin-bottom:16px}[_nghost-%COMP%] .arguments-list[_ngcontent-%COMP%]{padding:0}"]})}}e("ArgumentsMapConfigComponent",Oa);const Da=["operationInput"];function La(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"button",9),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.clear())})),t.ɵɵelementStart(1,"mat-icon",10),t.ɵɵtext(2,"close"),t.ɵɵelementEnd()()}}function Pa(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",11),t.ɵɵelement(1,"span",12),t.ɵɵpipe(2,"highlight"),t.ɵɵelementStart(3,"small",13),t.ɵɵtext(4),t.ɵɵelementEnd()()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e.value),t.ɵɵadvance(),t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(2,3,e.value+" | "+e.name,r.searchText),t.ɵɵsanitizeHtml),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",e.description," ")}}function Ra(e,n){1&e&&(t.ɵɵelementStart(0,"mat-option",11)(1,"span",3),t.ɵɵtext(2,"tb.rulenode.no-option-found"),t.ɵɵelementEnd()()),2&e&&t.ɵɵproperty("value",null)}class _a extends y{get required(){return this.requiredValue}set required(e){this.requiredValue=Z(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=[..._t.values()],this.propagateChange=null}ngOnInit(){this.mathFunctionForm=this.fb.group({operation:[""]}),this.filteredOptions=this.mathFunctionForm.get("operation").valueChanges.pipe(ae((e=>{let t;t="string"==typeof e&&Rt[e]?Rt[e]:null,this.updateView(t)})),te((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=_t.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)}static{this.ɵfac=function(e){return new(e||_a)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(t.Injector),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:_a,selectors:[["tb-math-function-autocomplete"]],viewQuery:function(e,n){if(1&e&&t.ɵɵviewQuery(Da,7),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.operationInput=e.first)}},inputs:{required:"required",disabled:"disabled"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>_a)),multi:!0}]),t.ɵɵInheritDefinitionFeature],decls:12,vars:11,consts:[["operationInput",""],["auto","matAutocomplete"],[1,"mat-block",3,"formGroup"],["translate",""],["type","text","matInput","","formControlName","operation",3,"focusin","required","matAutocomplete"],["type","button","matSuffix","","mat-icon-button","","aria-label","Clear",3,"click",4,"ngIf"],[1,"tb-autocomplete",3,"displayWith"],[3,"value",4,"ngFor","ngForOf"],[3,"value",4,"ngIf"],["type","button","matSuffix","","mat-icon-button","","aria-label","Clear",3,"click"],[1,"material-icons"],[3,"value"],[3,"innerHTML"],[2,"display","block","overflow","hidden","text-overflow","ellipsis","white-space","nowrap"]],template:function(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"mat-form-field",2)(1,"mat-label",3),t.ɵɵtext(2,"tb.rulenode.functions-field-input"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"input",4,0),t.ɵɵlistener("focusin",(function(){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.onFocus())})),t.ɵɵelementEnd(),t.ɵɵtemplate(5,La,3,0,"button",5),t.ɵɵelementStart(6,"mat-autocomplete",6,1),t.ɵɵtemplate(8,Pa,5,6,"mat-option",7),t.ɵɵpipe(9,"async"),t.ɵɵtemplate(10,Ra,3,1,"mat-option",8),t.ɵɵpipe(11,"async"),t.ɵɵelementEnd()()}if(2&e){let e;const r=t.ɵɵreference(7);t.ɵɵproperty("formGroup",n.mathFunctionForm),t.ɵɵadvance(3),t.ɵɵproperty("required",n.required)("matAutocomplete",r),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.mathFunctionForm.get("operation").value),t.ɵɵadvance(),t.ɵɵproperty("displayWith",n.mathFunctionDisplayFn),t.ɵɵadvance(2),t.ɵɵproperty("ngForOf",t.ɵɵpipeBind1(9,7,n.filteredOptions)),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!(null!=(e=t.ɵɵpipeBind1(11,9,n.filteredOptions))&&e.length))}},dependencies:t.ɵɵgetComponentDepsFactory(_a),encapsulation:2})}}function ja(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",8),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.name," ")}}function Ga(e,n){if(1&e&&(t.ɵɵelementStart(0,"button",9),t.ɵɵpipe(1,"translate"),t.ɵɵelementStart(2,"mat-icon",10),t.ɵɵtext(3,"content_copy "),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(1,2,"tb.rulenode.copy-message-type")),t.ɵɵproperty("cbContent",e.messageTypeFormGroup.get("messageType").value)}}function Ka(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.message-type-value-required")," "))}function Ua(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.message-type-value-max-length")," "))}e("MathFunctionAutocompleteComponent",_a);class Ha{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 Y,this.messageTypeFormGroup=this.fb.group({messageTypeAlias:[null,[N.required]],messageType:[{value:null,disabled:!0},[N.maxLength(255)]]}),this.messageTypeFormGroup.get("messageTypeAlias").valueChanges.pipe(W(this.destroy$)).subscribe((e=>this.updateMessageTypeValue(e))),this.messageTypeFormGroup.valueChanges.pipe(W(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?[N.required,N.maxLength(255)]:[N.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)}static{this.ɵfac=function(e){return new(e||Ha)(t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Ha,selectors:[["tb-output-message-type-autocomplete"]],inputs:{subscriptSizing:"subscriptSizing",disabled:"disabled",required:"required"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>Ha)),multi:!0},{provide:O,useExisting:r((()=>Ha)),multi:!0}])],decls:15,vars:14,consts:[[1,"tb-form-row","no-border","no-padding","tb-standard-fields","column-xs",3,"formGroup"],["hideRequiredMarker","",1,"flex",3,"subscriptSizing"],["formControlName","messageTypeAlias"],[3,"value",4,"ngFor","ngForOf"],[1,"flex",3,"subscriptSizing","hideRequiredMarker"],["matInput","","type","text","formControlName","messageType"],["type","button","matSuffix","","mat-icon-button","","aria-label","Copy","ngxClipboard","",3,"cbContent","matTooltip",4,"ngIf"],[4,"ngIf"],[3,"value"],["type","button","matSuffix","","mat-icon-button","","aria-label","Copy","ngxClipboard","",3,"cbContent","matTooltip"],["aria-hidden","false","aria-label","help-icon"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label"),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-select",2),t.ɵɵtemplate(6,ja,2,2,"mat-option",3),t.ɵɵelementEnd()(),t.ɵɵelementStart(7,"mat-form-field",4)(8,"mat-label"),t.ɵɵtext(9),t.ɵɵpipe(10,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(11,"input",5),t.ɵɵtemplate(12,Ga,4,4,"button",6)(13,Ka,3,3,"mat-error",7)(14,Ua,3,3,"mat-error",7),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.messageTypeFormGroup),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("subscriptSizing",n.subscriptSizing),t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(4,10,"tb.rulenode.output-message-type")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.messageTypes),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("subscriptSizing",n.subscriptSizing),t.ɵɵproperty("hideRequiredMarker",n.messageTypeFormGroup.get("messageType").disabled),t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(10,12,"tb.rulenode.message-type-value")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.messageTypeFormGroup.get("messageType").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.messageTypeFormGroup.get("messageType").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.messageTypeFormGroup.get("messageType").hasError("maxlength")))},dependencies:t.ɵɵgetComponentDepsFactory(Ha),encapsulation:2})}}e("OutputMessageTypeAutocompleteComponent",Ha),J([h()],Ha.prototype,"disabled",void 0),J([h()],Ha.prototype,"required",null);const za=(e,t)=>({keyText:e,valText:t});function $a(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,e.keyRequiredText)," ")}}function Qa(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,e.valRequiredText)," ")}}function Ja(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"div",10)(1,"mat-form-field",11),t.ɵɵelement(2,"input",12),t.ɵɵpipe(3,"translate"),t.ɵɵtemplate(4,$a,3,3,"mat-error",13),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-form-field",11),t.ɵɵelement(6,"input",12),t.ɵɵpipe(7,"translate"),t.ɵɵtemplate(8,Qa,3,3,"mat-error",13),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"button",14),t.ɵɵpipe(10,"translate"),t.ɵɵpipe(11,"async"),t.ɵɵlistener("click",(function(){const n=t.ɵɵrestoreView(e).index,r=t.ɵɵnextContext();return t.ɵɵresetView(r.removeKeyVal(n))})),t.ɵɵelementStart(12,"mat-icon"),t.ɵɵtext(13,"close"),t.ɵɵelementEnd()()()}if(2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("placeholder",t.ɵɵpipeBind1(3,10,r.keyText)),t.ɵɵproperty("formControl",e.get("key")),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",e.get("key").hasError("required")),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("placeholder",t.ɵɵpipeBind1(7,12,r.valText)),t.ɵɵproperty("formControl",e.get("value")),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",e.get("value").hasError("required")),t.ɵɵadvance(),t.ɵɵclassProp("!hidden",r.disabled),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(10,14,"tb.key-val.remove-entry")),t.ɵɵproperty("disabled",t.ɵɵpipeBind1(11,16,r.isLoading$))}}function Ya(e,n){if(1&e&&(t.ɵɵelement(0,"div",15),t.ɵɵpipe(1,"translate"),t.ɵɵpipe(2,"safe")),2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(2,3,t.ɵɵpipeBind1(1,1,e.hintText),"html"),t.ɵɵsanitizeHtml)}}class Wa extends y{get required(){return this.requiredValue}set required(e){this.requiredValue=Z(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,[N.required]],value:[e[n],[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:["",[N.required]],value:["",[N.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)}}static{this.ɵfac=function(e){return new(e||Wa)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(t.Injector),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Wa,selectors:[["tb-kv-map-config-old"]],inputs:{disabled:"disabled",uniqueKeyValuePairValidator:"uniqueKeyValuePairValidator",requiredText:"requiredText",keyText:"keyText",keyRequiredText:"keyRequiredText",valText:"valText",valRequiredText:"valRequiredText",hintText:"hintText",required:"required"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>Wa)),multi:!0},{provide:O,useExisting:r((()=>Wa)),multi:!0}]),t.ɵɵInheritDefinitionFeature],decls:21,vars:26,consts:[[1,"tb-kv-map-config","flex","flex-col",3,"formGroup"],[1,"header","flex","flex-1","flex-row","gap-2"],[1,"cell","tb-required","flex-1"],["innerHTML",t.ɵɵtrustConstantHtml` `,2,"width","52px"],[1,"body"],["class","row flex flex-row items-center justify-start gap-2","formArrayName","keyVals",4,"ngFor","ngForOf"],["class","tb-hint",3,"innerHTML",4,"ngIf"],[3,"error"],[2,"margin-top","16px"],["mat-button","","mat-raised-button","","color","primary","type","button","matTooltipPosition","above",3,"click","disabled","matTooltip"],["formArrayName","keyVals",1,"row","flex","flex-row","items-center","justify-start","gap-2"],[1,"cell","mat-block","flex-1"],["matInput","","required","",3,"formControl","placeholder"],[4,"ngIf"],["mat-icon-button","","color","primary","type","button","matTooltipPosition","above",3,"click","disabled","matTooltip"],[1,"tb-hint",3,"innerHTML"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"span",2),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"span",2),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(8,"span",3),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"div",4),t.ɵɵtemplate(10,Ja,14,18,"div",5)(11,Ya,3,6,"div",6),t.ɵɵelementEnd(),t.ɵɵelement(12,"tb-error",7),t.ɵɵelementStart(13,"div",8)(14,"button",9),t.ɵɵpipe(15,"translate"),t.ɵɵpipe(16,"async"),t.ɵɵlistener("click",(function(){return n.addKeyVal()})),t.ɵɵelementStart(17,"mat-icon"),t.ɵɵtext(18,"add"),t.ɵɵelementEnd(),t.ɵɵtext(19),t.ɵɵpipe(20,"translate"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.kvListFormGroup),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(4,13,n.keyText)),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(7,15,n.valText)),t.ɵɵadvance(2),t.ɵɵclassProp("!hidden",n.disabled),t.ɵɵadvance(2),t.ɵɵproperty("ngForOf",n.keyValsFormArray().controls),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.hintText),t.ɵɵadvance(),t.ɵɵproperty("error",n.ngControl.hasError("kvMapRequired")||n.ngControl.hasError("uniqueKeyValuePair")?n.ngControl.hasError("kvMapRequired")?n.translate.instant(n.requiredText):n.translate.instant("tb.key-val.unique-key-value-pair-error",t.ɵɵpureFunction2(23,za,n.translate.instant(n.keyText),n.translate.instant(n.valText))):""),t.ɵɵadvance(2),t.ɵɵclassProp("!hidden",n.disabled),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(15,17,"tb.key-val.add-entry")),t.ɵɵproperty("disabled",t.ɵɵpipeBind1(16,19,n.isLoading$)),t.ɵɵadvance(5),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(20,21,"action.add")," "))},dependencies:t.ɵɵgetComponentDepsFactory(Wa),styles:["[_nghost-%COMP%] .tb-kv-map-config[_ngcontent-%COMP%]{margin-bottom:16px}[_nghost-%COMP%] .tb-kv-map-config[_ngcontent-%COMP%] .header[_ngcontent-%COMP%]{padding-left:5px;padding-right:5px;padding-bottom:5px}[_nghost-%COMP%] .tb-kv-map-config[_ngcontent-%COMP%] .header[_ngcontent-%COMP%] .cell[_ngcontent-%COMP%]{padding-left:5px;padding-right:5px;color:#757575;font-size:12px;font-weight:700;white-space:nowrap}[_nghost-%COMP%] .tb-kv-map-config[_ngcontent-%COMP%] .header[_ngcontent-%COMP%] .tb-required[_ngcontent-%COMP%]:after{color:#757575;font-size:12px;font-weight:700}[_nghost-%COMP%] .tb-kv-map-config[_ngcontent-%COMP%] .body[_ngcontent-%COMP%]{padding-left:5px;padding-right:5px;padding-bottom:0;max-height:300px;overflow:auto}[_nghost-%COMP%] .tb-kv-map-config[_ngcontent-%COMP%] .body[_ngcontent-%COMP%] .cell[_ngcontent-%COMP%]{padding-left:5px;padding-right:5px}[_nghost-%COMP%] .tb-kv-map-config[_ngcontent-%COMP%] tb-error[_ngcontent-%COMP%]{display:block;margin-top:-12px}"]})}}function Xa(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-chip-option",4),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵpropertyInterpolate("selectable",r.chipControlGroup.get("chipControl").value!==e.value),t.ɵɵproperty("value",e.value),t.ɵɵadvance(),t.ɵɵtextInterpolate(e.name)}}e("KvMapConfigOldComponent",Wa);class Za{constructor(e,t){this.fb=e,this.translate=t,this.translation=Ht,this.propagateChange=()=>{},this.destroy$=new Y,this.selectOptions=[]}ngOnInit(){this.initOptions(),this.chipControlGroup=this.fb.group({chipControl:[null,[]]}),this.chipControlGroup.get("chipControl").valueChanges.pipe(ie(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})}static{this.ɵfac=function(e){return new(e||Za)(t.ɵɵdirectiveInject(k.FormBuilder),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Za,selectors:[["tb-msg-metadata-chip"]],inputs:{labelText:"labelText",translation:"translation"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>Za)),multi:!0}])],decls:5,vars:3,consts:[[1,"tb-form-row","space-between",3,"formGroup"],[1,"fixed-title-width"],["formControlName","chipControl"],["color","primary",3,"selectable","value",4,"ngFor","ngForOf"],["color","primary",3,"selectable","value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"div",0)(1,"div",1),t.ɵɵtext(2),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"mat-chip-listbox",2),t.ɵɵtemplate(4,Xa,2,3,"mat-chip-option",3),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.chipControlGroup),t.ɵɵadvance(2),t.ɵɵtextInterpolate(n.labelText),t.ɵɵadvance(2),t.ɵɵproperty("ngForOf",n.selectOptions))},dependencies:t.ɵɵgetComponentDepsFactory(Za),encapsulation:2})}}function ei(e,n){1&e&&(t.ɵɵelementStart(0,"div",13),t.ɵɵtext(1," tb.rulenode.map-fields-required "),t.ɵɵelementEnd())}function ti(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",13),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.requiredText," ")}}function ni(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",21),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e.value),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.name," ")}}function ri(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"div",14)(1,"mat-form-field",15)(2,"mat-select",16),t.ɵɵtemplate(3,ni,2,2,"mat-option",17),t.ɵɵelementEnd()(),t.ɵɵelementStart(4,"mat-form-field",15),t.ɵɵelement(5,"input",18),t.ɵɵelementEnd(),t.ɵɵelementStart(6,"div",19)(7,"button",20),t.ɵɵpipe(8,"translate"),t.ɵɵpipe(9,"async"),t.ɵɵlistener("click",(function(){const n=t.ɵɵrestoreView(e).index,r=t.ɵɵnextContext();return t.ɵɵresetView(r.removeKeyVal(n))})),t.ɵɵelementStart(10,"mat-icon"),t.ɵɵtext(11,"delete"),t.ɵɵelementEnd()()()()}if(2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵproperty("placeholder",r.selectText)("formControl",e.get("key")),t.ɵɵadvance(),t.ɵɵproperty("ngForOf",r.filterSelectOptions(e)),t.ɵɵadvance(2),t.ɵɵproperty("placeholder",r.valText)("formControl",e.get("value")),t.ɵɵadvance(2),t.ɵɵclassProp("tb-hidden",1===r.keyValsFormArray().controls.length),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(8,9,"tb.key-val.remove-mapping-entry")),t.ɵɵproperty("disabled",t.ɵɵpipeBind1(9,11,r.isLoading$))}}e("MsgMetadataChipComponent",Za);class ai extends y{constructor(e,t,n,r){super(e),this.store=e,this.translate=t,this.injector=n,this.fb=r,this.destroy$=new Y,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 w||e instanceof M){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 R(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(ie(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,[N.required]],value:[t.value,[N.required,N.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)P(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:["",[N.required]],value:["",[N.required,N.pattern(/(?:.|\s)*\S(&:.|\s)*/)]]})),this.keyChangeSubscribe(this.keyValsFormArray().at(this.keyValsFormArray().length-1))}keyChangeSubscribe(e){this.sourceFieldSubcritption.push(e.get("key").valueChanges.pipe(ie(this.destroy$)).subscribe((t=>{const n=ct.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)}}static{this.ɵfac=function(e){return new(e||ai)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(t.Injector),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:ai,selectors:[["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"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>ai)),multi:!0},{provide:O,useExisting:r((()=>ai)),multi:!0}]),t.ɵɵInheritDefinitionFeature],decls:22,vars:15,consts:[[1,"tb-form-panel","stroked",3,"formGroup"],[1,"tb-form-row","no-padding","no-border","space-between"],[1,"tb-form-panel-title"],["class","tb-form-panel-hint tb-error","translate","",4,"ngIf"],[1,"tb-form-panel","no-border","no-padding"],[1,"tb-form-table"],[1,"tb-form-table-header"],[1,"tb-form-table-header-cell","field-space"],[1,"tb-form-table-header-cell","actions-header"],[1,"tb-form-table-body"],["class","tb-form-table-row",4,"ngFor","ngForOf"],["type","button","mat-stroked-button","","color","primary",3,"click","disabled"],[3,"hintText","popupHelpLink"],["translate","",1,"tb-form-panel-hint","tb-error"],[1,"tb-form-table-row"],["appearance","outline","subscriptSizing","dynamic",1,"tb-inline-field","field-space"],["required","",3,"placeholder","formControl"],[3,"value",4,"ngFor","ngForOf"],["matInput","",3,"placeholder","formControl"],[1,"tb-form-table-row-cell-buttons"],["type","button","mat-icon-button","","matTooltipPosition","above",3,"click","disabled","matTooltip"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2),t.ɵɵtext(3),t.ɵɵelementEnd(),t.ɵɵtemplate(4,ei,2,0,"div",3)(5,ti,2,1,"div",3),t.ɵɵelementEnd(),t.ɵɵelementStart(6,"div",4)(7,"div",5)(8,"div",6)(9,"div",7),t.ɵɵtext(10),t.ɵɵelementEnd(),t.ɵɵelementStart(11,"div",7),t.ɵɵtext(12),t.ɵɵelementEnd(),t.ɵɵelement(13,"div",8),t.ɵɵelementEnd(),t.ɵɵelementStart(14,"div",9),t.ɵɵtemplate(15,ri,12,13,"div",10),t.ɵɵelementEnd()()(),t.ɵɵelementStart(16,"div")(17,"button",11),t.ɵɵpipe(18,"async"),t.ɵɵlistener("click",(function(){return n.addKeyVal()})),t.ɵɵtext(19),t.ɵɵpipe(20,"translate"),t.ɵɵelementEnd()(),t.ɵɵelement(21,"tb-example-hint",12),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.svListFormGroup),t.ɵɵadvance(3),t.ɵɵtextInterpolate(n.labelText),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.svListFormGroup.hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.svListFormGroup.hasError("svMapRequired")),t.ɵɵadvance(5),t.ɵɵtextInterpolate(n.selectText),t.ɵɵadvance(2),t.ɵɵtextInterpolate(n.valText),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.keyValsFormArray().controls),t.ɵɵadvance(2),t.ɵɵproperty("disabled",t.ɵɵpipeBind1(18,11,n.isLoading$)||n.keyValsFormArray().length>=n.selectOptions.length),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(20,13,"tb.key-val.add-mapping-entry")," "),t.ɵɵadvance(2),t.ɵɵproperty("hintText",n.hintText)("popupHelpLink",n.popupHelpLink))},dependencies:t.ɵɵgetComponentDepsFactory(ai),styles:["[_nghost-%COMP%] .field-space[_ngcontent-%COMP%]{flex:1 1 50%}[_nghost-%COMP%] .actions-header[_ngcontent-%COMP%]{width:40px}"]})}}function ii(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",11),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.directionTypeTranslations.get(e))," ")}}e("SvMapConfigComponent",ai),J([h()],ai.prototype,"disabled",void 0),J([h()],ai.prototype,"required",void 0);class oi extends y{get required(){return this.requiredValue}set required(e){this.requiredValue=Z(e)}constructor(e,t){super(e),this.store=e,this.fb=t,this.directionTypes=Object.keys(d),this.directionTypeTranslations=b,this.propagateChange=null}ngOnInit(){this.relationsQueryFormGroup=this.fb.group({fetchLastLevelOnly:[!1,[]],direction:[null,[N.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})}static{this.ɵfac=function(e){return new(e||oi)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:oi,selectors:[["tb-relations-query-config-old"]],inputs:{disabled:"disabled",required:"required"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>oi)),multi:!0}]),t.ɵɵInheritDefinitionFeature],decls:18,vars:8,consts:[[1,"flex","flex-col",3,"formGroup"],["formControlName","fetchLastLevelOnly"],[1,"flex","flex-row","gap-2"],[1,"mat-block",2,"min-width","100px"],["translate",""],["required","","matInput","","formControlName","direction"],[3,"value",4,"ngFor","ngForOf"],["floatLabel","always",1,"mat-block","flex-1"],["matInput","","type","number","min","1","step","1","formControlName","maxLevel",3,"placeholder"],["translate","",1,"mat-caption",2,"color","#6e6e6e"],["formControlName","filters"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-checkbox",1),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"div",2)(5,"mat-form-field",3)(6,"mat-label",4),t.ɵɵtext(7,"relation.direction"),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-select",5),t.ɵɵtemplate(9,ii,3,4,"mat-option",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(10,"mat-form-field",7)(11,"mat-label",4),t.ɵɵtext(12,"tb.rulenode.max-relation-level"),t.ɵɵelementEnd(),t.ɵɵelement(13,"input",8),t.ɵɵpipe(14,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(15,"div",9),t.ɵɵtext(16,"relation.relation-filters"),t.ɵɵelementEnd(),t.ɵɵelement(17,"tb-relation-filters",10),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.relationsQueryFormGroup),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(3,4,"alias.last-level-relation")," "),t.ɵɵadvance(7),t.ɵɵproperty("ngForOf",n.directionTypes),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("placeholder",t.ɵɵpipeBind1(14,6,"tb.rulenode.unlimited-level")))},dependencies:t.ɵɵgetComponentDepsFactory(oi),encapsulation:2})}}e("RelationsQueryConfigOldComponent",oi);const li=e=>({latestTsKeyName:e}),si=e=>({inputName:e});function pi(e,n){1&e&&t.ɵɵelementContainer(0,9)}function mi(e,n){1&e&&t.ɵɵelementContainer(0,9)}function di(e,n){1&e&&t.ɵɵelementContainer(0,9)}function ui(e,n){1&e&&t.ɵɵelementContainer(0,9)}function ci(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",10),t.ɵɵpipe(1,"translate"),t.ɵɵelementStart(2,"mat-slide-toggle",11),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind2(1,2,"tb.rulenode.fetch-latest-telemetry-with-timestamp-tooltip",t.ɵɵpureFunction1(7,li,e.attributeControlGroup.get("latestTsKeyNames").value[0]))),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(4,5,"tb.rulenode.fetch-latest-telemetry-with-timestamp")," ")}}function fi(e,n){1&e&&(t.ɵɵelementStart(0,"mat-icon",12),t.ɵɵpipe(1,"translate"),t.ɵɵpipe(2,"translate"),t.ɵɵtext(3,"help"),t.ɵɵelementEnd()),2&e&&t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind2(2,3,"tb.rulenode.chip-help",t.ɵɵpureFunction1(6,si,t.ɵɵpipeBind1(1,1,"tb.rulenode.field-name"))))}class gi{constructor(e,t){this.translate=e,this.fb=t,this.propagateChange=e=>{},this.destroy$=new Y,this.separatorKeysCodes=[U,H,z],this.onTouched=()=>{}}ngOnInit(){this.attributeControlGroup=this.fb.group({clientAttributeNames:[[],[]],sharedAttributeNames:[[],[]],serverAttributeNames:[[],[]],latestTsKeyNames:[[],[]],getLatestValueWithTs:[!1,[]]},{validators:this.atLeastOne(N.required,["clientAttributeNames","sharedAttributeNames","serverAttributeNames","latestTsKeyNames"])}),this.attributeControlGroup.valueChanges.pipe(ie(this.destroy$)).subscribe((e=>{this.propagateChange(this.preparePropagateValue(e))}))}preparePropagateValue(e){const t={};for(const n in e)t[n]="getLatestValueWithTs"===n||P(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()}static{this.ɵfac=function(e){return new(e||gi)(t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:gi,selectors:[["tb-select-attributes"]],inputs:{popupHelpLink:"popupHelpLink"},features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>gi)),multi:!0},{provide:O,useExisting:gi,multi:!0}])],decls:22,vars:34,consts:[["helpIcon",""],[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],[3,"hintText","popupHelpLink"],["subscriptSizing","dynamic","editable","","formControlName","clientAttributeNames",1,"mat-block",3,"focusout","placeholder","label"],["matSuffix","",4,"ngTemplateOutlet"],["subscriptSizing","dynamic","editable","","formControlName","sharedAttributeNames",1,"mat-block",3,"focusout","placeholder","label"],["subscriptSizing","dynamic","editable","","formControlName","serverAttributeNames",1,"mat-block",3,"focusout","placeholder","label"],["subscriptSizing","dynamic","editable","","formControlName","latestTsKeyNames",1,"mat-block",3,"focusout","placeholder","label"],["class","tb-form-row no-border no-padding",3,"tb-hint-tooltip-icon",4,"ngIf"],["matSuffix",""],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","getLatestValueWithTs",1,"mat-slide"],["aria-hidden","false","aria-label","help-icon","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"]],template:function(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"div",1),t.ɵɵelement(1,"tb-example-hint",2),t.ɵɵpipe(2,"translate"),t.ɵɵelementStart(3,"tb-string-items-list",3),t.ɵɵpipe(4,"translate"),t.ɵɵpipe(5,"translate"),t.ɵɵlistener("focusout",(function(){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.onTouched())})),t.ɵɵtemplate(6,pi,1,0,"ng-container",4),t.ɵɵelementEnd(),t.ɵɵelementStart(7,"tb-string-items-list",5),t.ɵɵpipe(8,"translate"),t.ɵɵpipe(9,"translate"),t.ɵɵlistener("focusout",(function(){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.onTouched())})),t.ɵɵtemplate(10,mi,1,0,"ng-container",4),t.ɵɵelementEnd(),t.ɵɵelementStart(11,"tb-string-items-list",6),t.ɵɵpipe(12,"translate"),t.ɵɵpipe(13,"translate"),t.ɵɵlistener("focusout",(function(){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.onTouched())})),t.ɵɵtemplate(14,di,1,0,"ng-container",4),t.ɵɵelementEnd(),t.ɵɵelementStart(15,"tb-string-items-list",7),t.ɵɵpipe(16,"translate"),t.ɵɵpipe(17,"translate"),t.ɵɵlistener("focusout",(function(){return t.ɵɵrestoreView(e),t.ɵɵresetView(n.onTouched())})),t.ɵɵtemplate(18,ui,1,0,"ng-container",4),t.ɵɵelementEnd(),t.ɵɵtemplate(19,ci,5,9,"div",8),t.ɵɵelementEnd(),t.ɵɵtemplate(20,fi,4,8,"ng-template",null,0,t.ɵɵtemplateRefExtractor)}if(2&e){let e;const r=t.ɵɵreference(21);t.ɵɵproperty("formGroup",n.attributeControlGroup),t.ɵɵadvance(),t.ɵɵproperty("hintText",t.ɵɵpipeBind1(2,16,"tb.rulenode.kv-map-pattern-hint"))("popupHelpLink",n.popupHelpLink),t.ɵɵadvance(2),t.ɵɵproperty("placeholder",t.ɵɵpipeBind1(4,18,"tb.rulenode.add-attribute-key"))("label",t.ɵɵpipeBind1(5,20,"tb.rulenode.client-attributes")),t.ɵɵadvance(3),t.ɵɵproperty("ngTemplateOutlet",r),t.ɵɵadvance(),t.ɵɵproperty("placeholder",t.ɵɵpipeBind1(8,22,"tb.rulenode.add-attribute-key"))("label",t.ɵɵpipeBind1(9,24,"tb.rulenode.shared-attributes")),t.ɵɵadvance(3),t.ɵɵproperty("ngTemplateOutlet",r),t.ɵɵadvance(),t.ɵɵproperty("placeholder",t.ɵɵpipeBind1(12,26,"tb.rulenode.add-attribute-key"))("label",t.ɵɵpipeBind1(13,28,"tb.rulenode.server-attributes")),t.ɵɵadvance(3),t.ɵɵproperty("ngTemplateOutlet",r),t.ɵɵadvance(),t.ɵɵproperty("placeholder",t.ɵɵpipeBind1(16,30,"tb.rulenode.add-telemetry-key"))("label",t.ɵɵpipeBind1(17,32,"tb.rulenode.latest-telemetry")),t.ɵɵadvance(3),t.ɵɵproperty("ngTemplateOutlet",r),t.ɵɵadvance(),t.ɵɵproperty("ngIf",(null==(e=n.attributeControlGroup.get("latestTsKeyNames").value)?null:e.length)>0)}},dependencies:t.ɵɵgetComponentDepsFactory(gi),encapsulation:2})}}e("SelectAttributesComponent",gi);class hi extends y{constructor(e,t){super(e),this.store=e,this.fb=t,this.propagateChange=null,this.destroy$=new Y,this.alarmStatus=x,this.alarmStatusTranslations=C}ngOnInit(){this.alarmStatusGroup=this.fb.group({alarmStatus:[null,[]]}),this.alarmStatusGroup.get("alarmStatus").valueChanges.pipe(ie(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})}static{this.ɵfac=function(e){return new(e||hi)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:hi,selectors:[["tb-alarm-status-select"]],features:[t.ɵɵProvidersFeature([{provide:V,useExisting:r((()=>hi)),multi:!0}]),t.ɵɵInheritDefinitionFeature],decls:16,vars:17,consts:[[1,"flex","flex-col","items-center","justify-center",3,"formGroup"],["multiple","","formControlName","alarmStatus",1,"chip-listbox","flex","flex-col"],[1,"toggle-column"],[1,"option","flex-1",3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-chip-listbox",1)(2,"div",2)(3,"mat-chip-option",3),t.ɵɵtext(4),t.ɵɵpipe(5,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(6,"mat-chip-option",3),t.ɵɵtext(7),t.ɵɵpipe(8,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(9,"div",2)(10,"mat-chip-option",3),t.ɵɵtext(11),t.ɵɵpipe(12,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(13,"mat-chip-option",3),t.ɵɵtext(14),t.ɵɵpipe(15,"translate"),t.ɵɵelementEnd()()()()),2&e&&(t.ɵɵproperty("formGroup",n.alarmStatusGroup),t.ɵɵadvance(3),t.ɵɵproperty("value",n.alarmStatus.ACTIVE_UNACK),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(5,9,n.alarmStatusTranslations.get(n.alarmStatus.ACTIVE_UNACK))," "),t.ɵɵadvance(2),t.ɵɵproperty("value",n.alarmStatus.ACTIVE_ACK),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(8,11,n.alarmStatusTranslations.get(n.alarmStatus.ACTIVE_ACK))," "),t.ɵɵadvance(3),t.ɵɵproperty("value",n.alarmStatus.CLEARED_UNACK),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(12,13,n.alarmStatusTranslations.get(n.alarmStatus.CLEARED_UNACK))," "),t.ɵɵadvance(2),t.ɵɵproperty("value",n.alarmStatus.CLEARED_ACK),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(15,15,n.alarmStatusTranslations.get(n.alarmStatus.CLEARED_ACK))," "))},dependencies:t.ɵɵgetComponentDepsFactory(hi),styles:["[_nghost-%COMP%] .chip-listbox[_ngcontent-%COMP%]{max-width:460px;width:100%}[_nghost-%COMP%] .chip-listbox[_ngcontent-%COMP%] .toggle-column[_ngcontent-%COMP%]{display:flex;flex:1 1 100%;gap:8px}[_nghost-%COMP%] .chip-listbox[_ngcontent-%COMP%] .option[_ngcontent-%COMP%]{margin:0}@media screen and (max-width: 959px){[_nghost-%COMP%] .chip-listbox[_ngcontent-%COMP%]{max-width:360px}[_nghost-%COMP%] .chip-listbox[_ngcontent-%COMP%] .toggle-column[_ngcontent-%COMP%]{flex-direction:column}}[_nghost-%COMP%] .chip-listbox .mdc-evolution-chip-set__chips{gap:8px}[_nghost-%COMP%] .chip-listbox .option button{flex-basis:100%;justify-content:start}[_nghost-%COMP%] .chip-listbox .option .mdc-evolution-chip__graphic{flex-grow:0}"]})}}e("AlarmStatusSelectComponent",hi);const yi=()=>({maxWidth:"820px"});function bi(e,n){if(1&e&&(t.ɵɵelement(0,"div",3),t.ɵɵpipe(1,"translate")),2&e){const e=t.ɵɵnextContext();t.ɵɵpropertyInterpolate("tb-help-popup",e.popupHelpLink),t.ɵɵpropertyInterpolate("trigger-text",t.ɵɵpipeBind1(1,3,"tb.key-val.see-examples")),t.ɵɵproperty("tb-help-popup-style",t.ɵɵpureFunction0(5,yi))}}class vi{constructor(){this.textAlign="left"}static{this.ɵfac=function(e){return new(e||vi)}}static{this.ɵcmp=t.ɵɵdefineComponent({type:vi,selectors:[["tb-example-hint"]],inputs:{hintText:"hintText",popupHelpLink:"popupHelpLink",textAlign:"textAlign"},decls:5,vars:10,consts:[[1,"tb-form-hint","tb-primary-fill","space-between",3,"hidden"],[1,"hint-text",3,"innerHTML"],["class","see-example","hintMode","","tb-help-popup-placement","right","trigger-style","letter-spacing:0.25px; font-size:12px",3,"tb-help-popup","tb-help-popup-style","trigger-text",4,"ngIf"],["hintMode","","tb-help-popup-placement","right","trigger-style","letter-spacing:0.25px; font-size:12px",1,"see-example",3,"tb-help-popup","tb-help-popup-style","trigger-text"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"div",0),t.ɵɵelement(1,"div",1),t.ɵɵpipe(2,"translate"),t.ɵɵpipe(3,"safe"),t.ɵɵtemplate(4,bi,2,6,"div",2),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("hidden",!n.hintText),t.ɵɵadvance(),t.ɵɵstyleProp("text-align",n.textAlign),t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(3,7,t.ɵɵpipeBind1(2,5,n.hintText),"html"),t.ɵɵsanitizeHtml),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.popupHelpLink))},dependencies:t.ɵɵgetComponentDepsFactory(vi),styles:["[_nghost-%COMP%] .space-between[_ngcontent-%COMP%]{display:flex;justify-content:space-between;gap:20px}[_nghost-%COMP%] .space-between[_ngcontent-%COMP%] .see-example[_ngcontent-%COMP%]{display:flex;flex-shrink:0}[_nghost-%COMP%] .hint-text[_ngcontent-%COMP%]{width:100%}"]})}}e("ExampleHintComponent",vi);class xi{static{this.ɵfac=function(e){return new(e||xi)}}static{this.ɵmod=t.ɵɵdefineNgModule({type:xi})}static{this.ɵinj=t.ɵɵdefineInjector({imports:[$,S,Q,_r,zr,Wr,ma,va,Oa,_a,Ha,Wa,Za,ai,oi,gi,hi,vi]})}}e("RulenodeCoreConfigCommonModule",xi),("undefined"==typeof ngJitMode||ngJitMode)&&t.ɵɵsetNgModuleScope(xi,{declarations:[_r,zr,Wr,ma,va,Oa,_a,Ha,Wa,Za,ai,oi,gi,hi,vi],imports:[$,S,Q],exports:[_r,zr,Wr,ma,va,Oa,_a,Ha,Wa,Za,ai,oi,gi,hi,vi]});class Ci{static{this.ɵfac=function(e){return new(e||Ci)}}static{this.ɵmod=t.ɵɵdefineNgModule({type:Ci})}static{this.ɵinj=t.ɵɵdefineInjector({imports:[$,S,Q,xi,Cr,ce,mr,rr,Vn,se,Ce,Re,He,$n,Ye,st,qn,Pn,er,lr,cr,fr,We,Zn,Yn,wr,Br]})}}e("RuleNodeCoreConfigActionModule",Ci),("undefined"==typeof ngJitMode||ngJitMode)&&t.ɵɵsetNgModuleScope(Ci,{declarations:[Cr,ce,mr,rr,Vn,se,Ce,Re,He,$n,Ye,st,qn,Pn,er,lr,cr,fr,We,Zn,Yn,wr,Br],imports:[$,S,Q,xi],exports:[Cr,ce,mr,rr,Vn,se,Ce,Re,He,$n,Ye,st,qn,Pn,er,lr,cr,fr,We,Zn,Yn,wr,Br]});const Si=e=>({inputValueKey:e}),Ti=e=>({periodValueKey:e}),Ii=(e,t)=>({outputValueKey:e,periodValueKey:t}),Ei=e=>({outputValueKey:e});function Fi(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.input-value-key-required")," "))}function qi(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.output-value-key-required")," "))}function Ai(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.number-of-digits-after-floating-point-range")," "))}function ki(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.number-of-digits-after-floating-point-range")," "))}function Ni(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.period-value-key-required")," "))}function wi(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",16)(1,"mat-label"),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",17),t.ɵɵtemplate(5,Ni,3,3,"mat-error",4),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(3,2,"tb.rulenode.period-value-key")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.calculateDeltaConfigForm.get("periodValueKey").hasError("required"))}}class Mi extends i{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[U,H,z]}configForm(){return this.calculateDeltaConfigForm}onConfigurationSet(e){this.calculateDeltaConfigForm=this.fb.group({inputValueKey:[e.inputValueKey,[N.required,N.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],outputValueKey:[e.outputValueKey,[N.required,N.pattern(/(?:.|\s)*\S(&:.|\s)*/)]],useCache:[e.useCache,[]],addPeriodBetweenMsgs:[e.addPeriodBetweenMsgs,[]],periodValueKey:[e.periodValueKey,[]],round:[e.round,[N.min(0),N.max(15)]],tellFailureIfDeltaIsNegative:[e.tellFailureIfDeltaIsNegative,[]],excludeZeroDeltas:[e.excludeZeroDeltas,[]]})}prepareInputConfig(e){return{inputValueKey:P(e?.inputValueKey)?e.inputValueKey:null,outputValueKey:P(e?.outputValueKey)?e.outputValueKey:null,useCache:!P(e?.useCache)||e.useCache,addPeriodBetweenMsgs:!!P(e?.addPeriodBetweenMsgs)&&e.addPeriodBetweenMsgs,periodValueKey:P(e?.periodValueKey)?e.periodValueKey:null,round:P(e?.round)?e.round:null,tellFailureIfDeltaIsNegative:!P(e?.tellFailureIfDeltaIsNegative)||e.tellFailureIfDeltaIsNegative,excludeZeroDeltas:!!P(e?.excludeZeroDeltas)&&e.excludeZeroDeltas}}prepareOutputConfig(e){return _(e)}updateValidators(e){this.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?this.calculateDeltaConfigForm.get("periodValueKey").setValidators([N.required]):this.calculateDeltaConfigForm.get("periodValueKey").setValidators([]),this.calculateDeltaConfigForm.get("periodValueKey").updateValueAndValidity({emitEvent:e})}validatorTriggers(){return["addPeriodBetweenMsgs"]}static{this.ɵfac=function(e){return new(e||Mi)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Mi,selectors:[["tb-enrichment-node-calculate-delta-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:50,vars:69,consts:[[3,"formGroup"],[1,"gt-sm:flex","gt-sm:flex-row","gt-sm:gap-5.5"],[1,"mat-block","flex-1"],["matInput","","formControlName","inputValueKey"],[4,"ngIf"],["matInput","","formControlName","outputValueKey"],["type","number","min","0","max","15","step","1","matInput","","formControlName","round"],[1,"tb-form-panel","no-padding","no-border"],[1,"tb-form-row","same-padding",3,"tb-hint-tooltip-icon"],["formControlName","tellFailureIfDeltaIsNegative",1,"mat-slide","margin"],["formControlName","useCache",1,"mat-slide","margin"],[1,"tb-form-panel","stroked"],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","addPeriodBetweenMsgs",1,"mat-slide"],["class","mat-block",4,"ngIf"],["formControlName","excludeZeroDeltas",1,"mat-slide","margin"],[1,"mat-block"],["required","","matInput","","formControlName","periodValueKey"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"mat-form-field",2)(3,"mat-label"),t.ɵɵtext(4),t.ɵɵpipe(5,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(6,"input",3),t.ɵɵtemplate(7,Fi,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-form-field",2)(9,"mat-label"),t.ɵɵtext(10),t.ɵɵpipe(11,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(12,"input",5),t.ɵɵtemplate(13,qi,3,3,"mat-error",4),t.ɵɵelementEnd()(),t.ɵɵelementStart(14,"mat-form-field",2)(15,"mat-label"),t.ɵɵtext(16),t.ɵɵpipe(17,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(18,"input",6),t.ɵɵtemplate(19,Ai,3,3,"mat-error",4)(20,ki,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(21,"div",7)(22,"div",8),t.ɵɵpipe(23,"translate"),t.ɵɵelementStart(24,"mat-slide-toggle",9),t.ɵɵtext(25),t.ɵɵpipe(26,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(27,"div",8),t.ɵɵpipe(28,"translate"),t.ɵɵpipe(29,"translate"),t.ɵɵelementStart(30,"mat-slide-toggle",10),t.ɵɵtext(31),t.ɵɵpipe(32,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(33,"div",11)(34,"div",12),t.ɵɵpipe(35,"translate"),t.ɵɵelementStart(36,"mat-slide-toggle",13),t.ɵɵtext(37),t.ɵɵpipe(38,"translate"),t.ɵɵpipe(39,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(40,wi,6,4,"mat-form-field",14),t.ɵɵelementEnd(),t.ɵɵelementStart(41,"div",8),t.ɵɵpipe(42,"translate"),t.ɵɵpipe(43,"translate"),t.ɵɵpipe(44,"translate"),t.ɵɵpipe(45,"translate"),t.ɵɵpipe(46,"translate"),t.ɵɵelementStart(47,"mat-slide-toggle",15),t.ɵɵtext(48),t.ɵɵpipe(49,"translate"),t.ɵɵelementEnd()()()()),2&e&&(t.ɵɵproperty("formGroup",n.calculateDeltaConfigForm),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(5,19,"tb.rulenode.input-value-key")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.calculateDeltaConfigForm.get("inputValueKey").hasError("required")||n.calculateDeltaConfigForm.get("inputValueKey").hasError("pattern")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(11,21,"tb.rulenode.output-value-key")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.calculateDeltaConfigForm.get("outputValueKey").hasError("required")||n.calculateDeltaConfigForm.get("outputValueKey").hasError("pattern")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(17,23,"tb.rulenode.number-of-digits-after-floating-point")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.calculateDeltaConfigForm.get("round").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.calculateDeltaConfigForm.get("round").hasError("max")),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(23,25,"tb.rulenode.failure-if-delta-negative-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(26,27,"tb.rulenode.failure-if-delta-negative")," "),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind2(29,31,"tb.rulenode.use-caching-tooltip",t.ɵɵpureFunction1(58,Si,n.calculateDeltaConfigForm.get("inputValueKey").valid?n.calculateDeltaConfigForm.get("inputValueKey").value:t.ɵɵpipeBind1(28,29,"tb.rulenode.input-value-key")))),t.ɵɵadvance(4),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(32,34,"tb.rulenode.use-caching")," "),t.ɵɵadvance(2),t.ɵɵclassProp("no-padding-bottom",n.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind2(35,36,"tb.rulenode.add-time-difference-between-readings-tooltip",t.ɵɵpureFunction1(60,Ti,n.calculateDeltaConfigForm.get("periodValueKey").valid&&n.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?n.calculateDeltaConfigForm.get("periodValueKey").value:"periodInMs"))),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind2(39,41,"tb.rulenode.add-time-difference-between-readings",t.ɵɵpureFunction1(62,Si,n.calculateDeltaConfigForm.get("inputValueKey").valid?n.calculateDeltaConfigForm.get("inputValueKey").value:t.ɵɵpipeBind1(38,39,"tb.rulenode.input-value-key")))," "),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",n.calculateDeltaConfigForm.get("addPeriodBetweenMsgs").value?t.ɵɵpipeBind2(44,48,"tb.rulenode.exclude-zero-deltas-time-difference-hint",t.ɵɵpureFunction2(64,Ii,n.calculateDeltaConfigForm.get("outputValueKey").valid?n.calculateDeltaConfigForm.get("outputValueKey").value:t.ɵɵpipeBind1(42,44,"tb.rulenode.output-value-key"),n.calculateDeltaConfigForm.get("periodValueKey").valid?n.calculateDeltaConfigForm.get("periodValueKey").value:t.ɵɵpipeBind1(43,46,"tb.rulenode.period-value-key"))):t.ɵɵpipeBind2(46,53,"tb.rulenode.exclude-zero-deltas-hint",t.ɵɵpureFunction1(67,Ei,n.calculateDeltaConfigForm.get("outputValueKey").valid?n.calculateDeltaConfigForm.get("outputValueKey").value:t.ɵɵpipeBind1(45,51,"tb.rulenode.output-value-key")))),t.ɵɵadvance(7),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(49,56,"tb.rulenode.exclude-zero-deltas")," "))},dependencies:t.ɵɵgetComponentDepsFactory(Mi),encapsulation:2})}}function Bi(e,n){if(1&e&&(t.ɵɵelementStart(0,"tb-toggle-option",8),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e.value),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.name," ")}}e("CalculateDeltaConfigComponent",Mi);class Vi extends i{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Ft;for(const e of qt.keys())e!==Ft.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(qt.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,_(e)}prepareInputConfig(e){let t,n;return t=P(e?.telemetry)?e.telemetry?Ft.LATEST_TELEMETRY:Ft.ATTRIBUTES:P(e?.dataToFetch)?e.dataToFetch:Ft.ATTRIBUTES,n=P(e?.attrMapping)?e.attrMapping:P(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:P(e?.fetchTo)?e.fetchTo:Kt.METADATA}}selectTranslation(e,t){return this.customerAttributesConfigForm.get("dataToFetch").value===Ft.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.customerAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[N.required]],fetchTo:[e.fetchTo]})}static{this.ɵfac=function(e){return new(e||Vi)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Vi,selectors:[["tb-enrichment-node-customer-attributes-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:17,vars:26,consts:[[1,"tb-form-panel","stroked",3,"formGroup"],["translate","",1,"tb-form-panel-title"],[1,"flex","flex-1","items-center","justify-center"],[1,"fetch-to-data-toggle"],["formControlName","dataToFetch","appearance","fill",1,"fetch-to-data-toggle"],[3,"value",4,"ngFor","ngForOf"],["required","","formControlName","dataMapping","popupHelpLink","rulenode/customer_attributes_node_fields_templatization",3,"requiredText","labelText","keyText","keyRequiredText","valText","valRequiredText","hintText"],["formControlName","fetchTo",3,"labelText"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵtext(2,"tb.rulenode.mapping-of-customers"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"div",2)(4,"div",3)(5,"tb-toggle-select",4),t.ɵɵtemplate(6,Bi,2,2,"tb-toggle-option",5),t.ɵɵelementEnd()()(),t.ɵɵelement(7,"tb-kv-map-config",6),t.ɵɵpipe(8,"translate"),t.ɵɵpipe(9,"translate"),t.ɵɵpipe(10,"translate"),t.ɵɵpipe(11,"translate"),t.ɵɵpipe(12,"translate"),t.ɵɵpipe(13,"translate"),t.ɵɵelement(14,"tb-msg-metadata-chip",7),t.ɵɵpipe(15,"translate"),t.ɵɵpipe(16,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.customerAttributesConfigForm),t.ɵɵadvance(6),t.ɵɵproperty("ngForOf",n.fetchToData),t.ɵɵadvance(),t.ɵɵproperty("requiredText",t.ɵɵpipeBind1(8,10,"tb.rulenode.attr-mapping-required"))("labelText",t.ɵɵpipeBind1(9,12,n.selectTranslation("tb.rulenode.latest-telemetry-mapping","tb.rulenode.attributes-mapping")))("keyText",t.ɵɵpipeBind1(10,14,n.selectTranslation("tb.rulenode.source-telemetry","tb.rulenode.source-attribute")))("keyRequiredText",t.ɵɵpipeBind1(11,16,n.selectTranslation("tb.rulenode.source-telemetry-required","tb.rulenode.source-attribute-required")))("valText",t.ɵɵpipeBind1(12,18,"tb.rulenode.target-key"))("valRequiredText",t.ɵɵpipeBind1(13,20,"tb.rulenode.target-key-required"))("hintText","tb.rulenode.kv-map-pattern-hint"),t.ɵɵadvance(7),t.ɵɵproperty("labelText",n.customerAttributesConfigForm.get("dataToFetch").value===n.DataToFetch.LATEST_TELEMETRY?t.ɵɵpipeBind1(15,22,"tb.rulenode.add-mapped-latest-telemetry-to"):t.ɵɵpipeBind1(16,24,"tb.rulenode.add-mapped-attribute-to")))},dependencies:t.ɵɵgetComponentDepsFactory(Vi),styles:["[_nghost-%COMP%] .fetch-to-data-toggle[_ngcontent-%COMP%]{max-width:420px;width:100%}"]})}}e("CustomerAttributesConfigComponent",Vi);class Oi extends i{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,[N.required]],tellFailureIfAbsent:[e.tellFailureIfAbsent,[]],fetchTo:[e.fetchTo,[]],attributesControl:[e.attributesControl,[]]})}prepareInputConfig(e){return j(e)&&(e.attributesControl={clientAttributeNames:P(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:P(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:P(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:P(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!P(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{deviceRelationsQuery:P(e?.deviceRelationsQuery)?e.deviceRelationsQuery:null,tellFailureIfAbsent:!P(e?.tellFailureIfAbsent)||e.tellFailureIfAbsent,fetchTo:P(e?.fetchTo)?e.fetchTo:Kt.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}static{this.ɵfac=function(e){return new(e||Oi)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Oi,selectors:[["tb-enrichment-node-device-attributes-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:19,vars:11,consts:[[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],[1,"tb-form-panel","stroked","no-padding-bottom"],["translate","",1,"tb-form-panel-title"],["required","","formControlName","deviceRelationsQuery"],[1,"tb-form-panel","stroked"],[1,"tb-form-row","no-padding","no-border","space-between"],["translate","",1,"tb-form-panel-title","tb-required"],["translate","",1,"tb-form-panel-hint","tb-error",3,"hidden"],["formControlName","attributesControl","popupHelpLink","rulenode/related_device_attributes_node_fields_templatization"],["formControlName","fetchTo",3,"labelText"],[1,"tb-form-row","same-padding",3,"tb-hint-tooltip-icon"],["formControlName","tellFailureIfAbsent",1,"mat-slide","margin"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2),t.ɵɵtext(3,"tb.rulenode.device-relations-query"),t.ɵɵelementEnd(),t.ɵɵelement(4,"tb-device-relations-query-config",3),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"div",4)(6,"div",5)(7,"div",6),t.ɵɵtext(8,"tb.rulenode.related-device-attributes"),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"div",7),t.ɵɵtext(10," tb.rulenode.at-least-one-field-required "),t.ɵɵelementEnd()(),t.ɵɵelement(11,"tb-select-attributes",8)(12,"tb-msg-metadata-chip",9),t.ɵɵpipe(13,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(14,"div",10),t.ɵɵpipe(15,"translate"),t.ɵɵelementStart(16,"mat-slide-toggle",11),t.ɵɵtext(17),t.ɵɵpipe(18,"translate"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.deviceAttributesConfigForm),t.ɵɵadvance(9),t.ɵɵproperty("hidden",!(n.deviceAttributesConfigForm.get("attributesControl").touched&&n.deviceAttributesConfigForm.get("attributesControl").hasError("atLeastOneRequired"))),t.ɵɵadvance(3),t.ɵɵproperty("labelText",t.ɵɵpipeBind1(13,5,"tb.rulenode.add-selected-attributes-to")),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(15,7,"tb.rulenode.tell-failure-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(18,9,"tb.rulenode.tell-failure")," "))},dependencies:t.ɵɵgetComponentDepsFactory(Oi),encapsulation:2})}}e("DeviceAttributesConfigComponent",Oi);const Di=e=>({inputName:e});class Li extends i{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.predefinedValues=[];for(const e of Object.keys(xt))this.predefinedValues.push({value:xt[e],name:this.translate.instant(Ct.get(xt[e]))})}ngOnInit(){super.ngOnInit()}configForm(){return this.entityDetailsConfigForm}prepareInputConfig(e){let t;return t=P(e?.addToMetadata)?e.addToMetadata?Kt.METADATA:Kt.DATA:e?.fetchTo?e.fetchTo:Kt.DATA,{detailsList:P(e?.detailsList)?e.detailsList:null,fetchTo:t}}onConfigurationSet(e){this.entityDetailsConfigForm=this.fb.group({detailsList:[e.detailsList,[N.required]],fetchTo:[e.fetchTo,[]]})}static{this.ɵfac=function(e){return new(e||Li)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Li,selectors:[["tb-enrichment-node-entity-details-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:11,vars:22,consts:[[3,"formGroup"],["required","","formControlName","detailsList",1,"mat-block",3,"predefinedValues","label","placeholder","requiredText"],["matSuffix","","aria-hidden","false","aria-label","help-icon","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],["formControlName","fetchTo",3,"labelText"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"tb-string-items-list",1),t.ɵɵpipe(2,"translate"),t.ɵɵpipe(3,"translate"),t.ɵɵpipe(4,"translate"),t.ɵɵelementStart(5,"mat-icon",2),t.ɵɵpipe(6,"translate"),t.ɵɵpipe(7,"translate"),t.ɵɵtext(8," help "),t.ɵɵelementEnd()(),t.ɵɵelement(9,"tb-msg-metadata-chip",3),t.ɵɵpipe(10,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.entityDetailsConfigForm),t.ɵɵadvance(),t.ɵɵproperty("predefinedValues",n.predefinedValues)("label",t.ɵɵpipeBind1(2,7,"tb.rulenode.select-details"))("placeholder",t.ɵɵpipeBind1(3,9,"tb.rulenode.add-detail"))("requiredText",t.ɵɵpipeBind1(4,11,"tb.rulenode.entity-details-list-empty")),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind2(7,15,"tb.rulenode.chip-help",t.ɵɵpureFunction1(20,Di,t.ɵɵpipeBind1(6,13,"tb.rulenode.detail")))),t.ɵɵadvance(4),t.ɵɵproperty("labelText",t.ɵɵpipeBind1(10,18,"tb.rulenode.add-selected-details-to")))},dependencies:t.ɵɵgetComponentDepsFactory(Li),encapsulation:2})}}e("EntityDetailsConfigComponent",Li);const Pi=()=>({maxWidth:"820px"}),Ri=e=>({inputName:e}),_i=(e,t,n,r)=>({startInterval:e,endInterval:t,startIntervalTimeUnit:n,endIntervalTimeUnit:r});function ji(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.start-interval-value-required")," "))}function Gi(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.time-value-range")," "))}function Ki(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.time-value-range")," "))}function Ui(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",29),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.timeUnitsTranslationMap.get(e))," ")}}function Hi(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.end-interval-value-required")," "))}function zi(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.time-value-range")," "))}function $i(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.time-value-range")," "))}function Qi(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",29),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.timeUnitsTranslationMap.get(e))," ")}}function Ji(e,n){if(1&e&&(t.ɵɵelementContainerStart(0),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementContainerEnd()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind2(2,1,"tb.rulenode.fetch-timeseries-from-to",t.ɵɵpureFunction4(4,_i,e.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").value,e.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").value,e.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").value.toLowerCase(),e.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").value.toLowerCase()))," ")}}function Yi(e,n){1&e&&(t.ɵɵtext(0),t.ɵɵpipe(1,"translate")),2&e&&t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(1,1,"tb.rulenode.fetch-timeseries-from-to-invalid")," ")}function Wi(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",17)(1,"div",18)(2,"mat-form-field",19)(3,"mat-label"),t.ɵɵtext(4),t.ɵɵpipe(5,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(6,"input",20),t.ɵɵtemplate(7,ji,3,3,"mat-error",16)(8,Gi,3,3,"mat-error",16)(9,Ki,3,3,"mat-error",16),t.ɵɵelementEnd(),t.ɵɵelementStart(10,"mat-form-field",21)(11,"mat-label"),t.ɵɵtext(12),t.ɵɵpipe(13,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(14,"mat-select",22),t.ɵɵtemplate(15,Ui,3,4,"mat-option",14),t.ɵɵelementEnd()()(),t.ɵɵelementStart(16,"div",18)(17,"mat-form-field",19)(18,"mat-label"),t.ɵɵtext(19),t.ɵɵpipe(20,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(21,"input",23),t.ɵɵtemplate(22,Hi,3,3,"mat-error",16)(23,zi,3,3,"mat-error",16)(24,$i,3,3,"mat-error",16),t.ɵɵelementEnd(),t.ɵɵelementStart(25,"mat-form-field",21)(26,"mat-label"),t.ɵɵtext(27),t.ɵɵpipe(28,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(29,"mat-select",24),t.ɵɵtemplate(30,Qi,3,4,"mat-option",14),t.ɵɵelementEnd()()(),t.ɵɵelementStart(31,"div",25)(32,"mat-icon",26),t.ɵɵtext(33,"error_outline"),t.ɵɵelementEnd(),t.ɵɵelementStart(34,"div",27),t.ɵɵtemplate(35,Ji,3,9,"ng-container",28)(36,Yi,2,3,"ng-template",null,1,t.ɵɵtemplateRefExtractor),t.ɵɵelementEnd()()()),2&e){const e=t.ɵɵreference(37),n=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(5,16,"tb.rulenode.interval-start")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").hasError("max")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(13,18,"tb.rulenode.time-unit")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.timeUnits),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(20,20,"tb.rulenode.interval-end")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").hasError("max")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(28,22,"tb.rulenode.time-unit")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.timeUnits),t.ɵɵadvance(),t.ɵɵclassProp("error",n.getTelemetryFromDatabaseConfigForm.get("interval").invalid),t.ɵɵadvance(4),t.ɵɵproperty("ngIf",n.getTelemetryFromDatabaseConfigForm.get("interval").valid)("ngIfElse",e)}}function Xi(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.start-interval-required")," "))}function Zi(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.end-interval-required")," "))}function eo(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",30)(1,"mat-form-field",31)(2,"mat-label"),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(5,"input",32),t.ɵɵtemplate(6,Xi,3,3,"mat-error",16),t.ɵɵelementEnd(),t.ɵɵelementStart(7,"mat-form-field",31)(8,"mat-label"),t.ɵɵtext(9),t.ɵɵpipe(10,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(11,"input",33),t.ɵɵtemplate(12,Zi,3,3,"mat-error",16),t.ɵɵelementEnd(),t.ɵɵelement(13,"tb-example-hint",34),t.ɵɵpipe(14,"translate"),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(4,5,"tb.rulenode.start-interval")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").hasError("required")||e.getTelemetryFromDatabaseConfigForm.get("startIntervalPattern").hasError("pattern")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(10,7,"tb.rulenode.end-interval")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").hasError("required")||e.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").hasError("pattern")),t.ɵɵadvance(),t.ɵɵproperty("hintText",t.ɵɵpipeBind1(14,9,"tb.rulenode.metadata-dynamic-interval-hint"))}}function to(e,n){if(1&e&&(t.ɵɵelementStart(0,"tb-toggle-option",29),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e.value),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.name," ")}}function no(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",29),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.aggregationTypesTranslations.get(r.aggregationTypes[e]))," ")}}function ro(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",29),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(3);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.samplingOrdersTranslate.get(e))," ")}}function ao(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.limit-required")," "))}function io(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.limit-range")," "))}function oo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.limit-range")," "))}function lo(e,n){if(1&e&&(t.ɵɵelementStart(0,"div")(1,"mat-form-field",37)(2,"mat-label"),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-select",38),t.ɵɵtemplate(6,ro,3,4,"mat-option",14),t.ɵɵelementEnd()(),t.ɵɵelementStart(7,"mat-form-field",39)(8,"mat-label"),t.ɵɵtext(9),t.ɵɵpipe(10,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(11,"input",40),t.ɵɵelementStart(12,"mat-hint"),t.ɵɵtext(13),t.ɵɵpipe(14,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(15,ao,3,3,"mat-error",16)(16,io,3,3,"mat-error",16)(17,oo,3,3,"mat-error",16),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(4,7,"tb.rulenode.order-by-timestamp")," "),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",e.samplingOrders),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(10,9,"tb.rulenode.limit")),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(14,11,"tb.rulenode.limit-hint")),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",e.getTelemetryFromDatabaseConfigForm.get("limit").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.getTelemetryFromDatabaseConfigForm.get("limit").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.getTelemetryFromDatabaseConfigForm.get("limit").hasError("max"))}}function so(e,n){if(1&e&&(t.ɵɵelementStart(0,"div")(1,"mat-form-field",35)(2,"mat-label"),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-select",36),t.ɵɵtemplate(6,no,3,4,"mat-option",14),t.ɵɵelementEnd()(),t.ɵɵtemplate(7,lo,18,13,"div",16),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵproperty("subscriptSizing",e.defaultPaddingEnable()?"fixed":"dynamic"),t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(4,4,"aggregation.function")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",e.aggregations),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.getTelemetryFromDatabaseConfigForm.get("aggregation").value===e.aggregationTypes.NONE)}}class po extends i{constructor(e,t,n){super(e),this.store=e,this.translate=t,this.fb=n,this.separatorKeysCodes=[U,H,z],this.aggregationTypes=T,this.aggregations=Object.values(T),this.aggregationTypesTranslations=I,this.fetchMode=St,this.samplingOrders=Object.values(Et),this.samplingOrdersTranslate=kt,this.timeUnits=Object.values(ht),this.timeUnitsTranslationMap=yt,this.deduplicationStrategiesHintTranslations=It,this.headerOptions=[],this.timeUnitMap={[ht.MILLISECONDS]:1,[ht.SECONDS]:1e3,[ht.MINUTES]:6e4,[ht.HOURS]:36e5,[ht.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 Tt.keys())this.headerOptions.push({value:e,name:this.translate.instant(Tt.get(e))})}configForm(){return this.getTelemetryFromDatabaseConfigForm}onConfigurationSet(e){this.getTelemetryFromDatabaseConfigForm=this.fb.group({latestTsKeyNames:[e.latestTsKeyNames,[N.required]],aggregation:[e.aggregation,[N.required]],fetchMode:[e.fetchMode,[N.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,_(e)}prepareInputConfig(e){return j(e)&&(e.interval={startInterval:e.startInterval,startIntervalTimeUnit:e.startIntervalTimeUnit,endInterval:e.endInterval,endIntervalTimeUnit:e.endIntervalTimeUnit}),{latestTsKeyNames:P(e?.latestTsKeyNames)?e.latestTsKeyNames:null,aggregation:P(e?.aggregation)?e.aggregation:T.NONE,fetchMode:P(e?.fetchMode)?e.fetchMode:St.FIRST,orderBy:P(e?.orderBy)?e.orderBy:Et.ASC,limit:P(e?.limit)?e.limit:1e3,useMetadataIntervalPatterns:!!P(e?.useMetadataIntervalPatterns)&&e.useMetadataIntervalPatterns,interval:{startInterval:P(e?.interval?.startInterval)?e.interval.startInterval:2,startIntervalTimeUnit:P(e?.interval?.startIntervalTimeUnit)?e.interval.startIntervalTimeUnit:ht.MINUTES,endInterval:P(e?.interval?.endInterval)?e.interval.endInterval:1,endIntervalTimeUnit:P(e?.interval?.endIntervalTimeUnit)?e.interval.endIntervalTimeUnit:ht.MINUTES},startIntervalPattern:P(e?.startIntervalPattern)?e.startIntervalPattern:null,endIntervalPattern:P(e?.endIntervalPattern)?e.endIntervalPattern:null}}updateValidators(e){const t=this.getTelemetryFromDatabaseConfigForm.get("fetchMode").value,n=this.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value;t&&t===St.ALL?(this.getTelemetryFromDatabaseConfigForm.get("aggregation").setValidators([N.required]),this.getTelemetryFromDatabaseConfigForm.get("orderBy").setValidators([N.required]),this.getTelemetryFromDatabaseConfigForm.get("limit").setValidators([N.required,N.min(2),N.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([N.required,N.pattern(/(?:.|\s)*\S(&:.|\s)*/)]),this.getTelemetryFromDatabaseConfigForm.get("endIntervalPattern").setValidators([N.required,N.pattern(/(?:.|\s)*\S(&:.|\s)*/)])):(this.getTelemetryFromDatabaseConfigForm.get("interval.startInterval").setValidators([N.required,N.min(1),N.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.startIntervalTimeUnit").setValidators([N.required]),this.getTelemetryFromDatabaseConfigForm.get("interval.endInterval").setValidators([N.required,N.min(1),N.max(2147483647)]),this.getTelemetryFromDatabaseConfigForm.get("interval.endIntervalTimeUnit").setValidators([N.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===St.ALL&&this.getTelemetryFromDatabaseConfigForm.get("aggregation").value===T.NONE}static{this.ɵfac=function(e){return new(e||po)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:po,selectors:[["tb-enrichment-node-get-telemetry-from-database"]],features:[t.ɵɵInheritDefinitionFeature],decls:34,vars:40,consts:[["intervalPattern",""],["invalidText",""],[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],["editable","","subscriptSizing","dynamic","required","","formControlName","latestTsKeyNames",1,"mat-block",3,"placeholder","requiredText","label","hint"],["matHintEnd","","hintMode","","tb-help-popup-placement","right","trigger-style","letter-spacing:0.25px; font-size:12px",1,"see-example",3,"tb-help-popup","tb-help-popup-style","trigger-text"],["matSuffix","","aria-hidden","false","aria-label","help-icon","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],[1,"tb-form-panel","stroked"],["translate","",1,"tb-form-panel-title"],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","useMetadataIntervalPatterns",1,"mat-slide"],["formGroupName","interval","class","flex flex-col",4,"ngIf","ngIfElse"],[1,"tb-form-panel","no-border","no-padding","item-center"],[1,"fetch-mod-toggle"],["formControlName","fetchMode","appearance","fill"],[3,"value",4,"ngFor","ngForOf"],[1,"tb-form-hint","tb-primary-fill","hint-container"],[4,"ngIf"],["formGroupName","interval",1,"flex","flex-col"],[1,"flex","flex-col","gap-0","gt-sm:flex-row","gt-sm:gap-4"],[1,"mat-block","gt-sm:max-w-50%","gt-sm:flex-full"],["type","number","step","1","min","1","max","2147483647","matInput","","formControlName","startInterval","required",""],["hideRequiredMarker","",1,"mat-block","gt-sm:max-w-50%","gt-sm:flex-full"],["formControlName","startIntervalTimeUnit","required",""],["type","number","step","1","min","1","max","2147483647","matInput","","formControlName","endInterval","required",""],["formControlName","endIntervalTimeUnit","required",""],[1,"description-block","tb-primary-fill"],[1,"description-icon"],[1,"description-text"],[4,"ngIf","ngIfElse"],[3,"value"],[1,"input-block","flex","flex-col"],[1,"mat-block","flex-1"],["matInput","","formControlName","startIntervalPattern","required",""],["matInput","","formControlName","endIntervalPattern","required",""],["popupHelpLink","rulenode/originator_telemetry_node_fields_templatization",3,"hintText"],["hideRequiredMarker","",1,"mat-block",3,"subscriptSizing"],["formControlName","aggregation","required",""],["hideRequiredMarker","",1,"mat-block"],["formControlName","orderBy","required",""],[1,"mat-block"],["type","number","min","2","max","1000","step","1","matInput","","formControlName","limit","required",""]],template:function(e,n){if(1&e&&(t.ɵɵelementStart(0,"section",2)(1,"tb-string-items-list",3),t.ɵɵpipe(2,"translate"),t.ɵɵpipe(3,"translate"),t.ɵɵpipe(4,"translate"),t.ɵɵpipe(5,"translate"),t.ɵɵelement(6,"div",4),t.ɵɵpipe(7,"translate"),t.ɵɵelementStart(8,"mat-icon",5),t.ɵɵpipe(9,"translate"),t.ɵɵpipe(10,"translate"),t.ɵɵtext(11,"help "),t.ɵɵelementEnd()(),t.ɵɵelementStart(12,"div",6)(13,"div",7),t.ɵɵtext(14,"tb.rulenode.fetch-interval"),t.ɵɵelementEnd(),t.ɵɵelementStart(15,"div",8),t.ɵɵpipe(16,"translate"),t.ɵɵelementStart(17,"mat-slide-toggle",9),t.ɵɵtext(18),t.ɵɵpipe(19,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(20,Wi,38,24,"div",10)(21,eo,15,11,"ng-template",null,0,t.ɵɵtemplateRefExtractor),t.ɵɵelementEnd(),t.ɵɵelementStart(23,"div",6)(24,"div",7),t.ɵɵtext(25,"tb.rulenode.fetch-strategy"),t.ɵɵelementEnd(),t.ɵɵelementStart(26,"div",11)(27,"div",12)(28,"tb-toggle-select",13),t.ɵɵtemplate(29,to,2,2,"tb-toggle-option",14),t.ɵɵelementEnd()(),t.ɵɵelementStart(30,"div",15),t.ɵɵtext(31),t.ɵɵpipe(32,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(33,so,8,6,"div",16),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵreference(22);t.ɵɵproperty("formGroup",n.getTelemetryFromDatabaseConfigForm),t.ɵɵadvance(),t.ɵɵproperty("placeholder",t.ɵɵpipeBind1(2,16,"tb.rulenode.add-timeseries-key"))("requiredText",t.ɵɵpipeBind1(3,18,"tb.rulenode.timeseries-keys-required"))("label",t.ɵɵpipeBind1(4,20,"tb.rulenode.timeseries-keys"))("hint",t.ɵɵpipeBind1(5,22,"tb.rulenode.general-pattern-hint")),t.ɵɵadvance(5),t.ɵɵpropertyInterpolate("tb-help-popup","rulenode/originator_telemetry_node_fields_templatization"),t.ɵɵpropertyInterpolate("trigger-text",t.ɵɵpipeBind1(7,24,"tb.key-val.see-examples")),t.ɵɵproperty("tb-help-popup-style",t.ɵɵpureFunction0(37,Pi)),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind2(10,28,"tb.rulenode.chip-help",t.ɵɵpureFunction1(38,Ri,t.ɵɵpipeBind1(9,26,"tb.rulenode.timeseries-key")))),t.ɵɵadvance(7),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(16,31,"tb.rulenode.use-metadata-dynamic-interval-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(19,33,"tb.rulenode.use-metadata-dynamic-interval")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!1===n.getTelemetryFromDatabaseConfigForm.get("useMetadataIntervalPatterns").value)("ngIfElse",e),t.ɵɵadvance(9),t.ɵɵproperty("ngForOf",n.headerOptions),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(32,35,n.deduplicationStrategiesHintTranslations.get(n.getTelemetryFromDatabaseConfigForm.get("fetchMode").value))," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.getTelemetryFromDatabaseConfigForm.get("fetchMode").value===n.fetchMode.ALL)}},dependencies:t.ɵɵgetComponentDepsFactory(po),styles:["[_nghost-%COMP%] .see-example[_ngcontent-%COMP%]{display:inline-block}[_nghost-%COMP%] .description-block[_ngcontent-%COMP%]{display:flex;align-items:center;border-radius:6px;border:1px solid #EAEAEA}[_nghost-%COMP%] .description-block[_ngcontent-%COMP%] .description-icon[_ngcontent-%COMP%]{font-size:24px;height:24px;min-height:24px;width:24px;min-width:24px;line-height:24px;color:#d9d9d9;margin:4px}[_nghost-%COMP%] .description-block[_ngcontent-%COMP%] .description-text[_ngcontent-%COMP%]{font-size:12px;line-height:16px;letter-spacing:.25px;margin:6px}[_nghost-%COMP%] .description-block.error[_ngcontent-%COMP%]{color:var(--mdc-theme-error, #f44336)}[_nghost-%COMP%] .description-block.error[_ngcontent-%COMP%] .description-icon[_ngcontent-%COMP%]{color:var(--mdc-theme-error, #f44336)}[_nghost-%COMP%] .item-center[_ngcontent-%COMP%]{align-items:center}[_nghost-%COMP%] .item-center[_ngcontent-%COMP%] .fetch-mod-toggle[_ngcontent-%COMP%]{width:100%}[_nghost-%COMP%] .hint-container[_ngcontent-%COMP%]{width:100%}"]})}}e("GetTelemetryFromDatabaseConfigComponent",po);class mo extends i{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 j(e)&&(e.attributesControl={clientAttributeNames:P(e?.clientAttributeNames)?e.clientAttributeNames:[],latestTsKeyNames:P(e?.latestTsKeyNames)?e.latestTsKeyNames:[],serverAttributeNames:P(e?.serverAttributeNames)?e.serverAttributeNames:[],sharedAttributeNames:P(e?.sharedAttributeNames)?e.sharedAttributeNames:[],getLatestValueWithTs:!!P(e?.getLatestValueWithTs)&&e.getLatestValueWithTs}),{fetchTo:P(e?.fetchTo)?e.fetchTo:Kt.METADATA,tellFailureIfAbsent:!!P(e?.tellFailureIfAbsent)&&e.tellFailureIfAbsent,attributesControl:P(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}static{this.ɵfac=function(e){return new(e||mo)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(K.TranslateService),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:mo,selectors:[["tb-enrichment-node-originator-attributes-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:15,vars:11,consts:[[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],[1,"tb-form-panel","stroked"],[1,"tb-form-row","no-padding","no-border","space-between"],["translate","",1,"tb-form-panel-title","tb-required"],["translate","",1,"tb-form-panel-hint","tb-error",3,"hidden"],["formControlName","attributesControl","popupHelpLink","rulenode/originator_attributes_node_fields_templatization"],["formControlName","fetchTo",3,"labelText"],[1,"tb-form-row","same-padding",3,"tb-hint-tooltip-icon"],["formControlName","tellFailureIfAbsent",1,"mat-slide","margin"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2)(3,"div",3),t.ɵɵtext(4,"tb.rulenode.originator-attributes"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"div",4),t.ɵɵtext(6," tb.rulenode.at-least-one-field-required "),t.ɵɵelementEnd()(),t.ɵɵelement(7,"tb-select-attributes",5)(8,"tb-msg-metadata-chip",6),t.ɵɵpipe(9,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(10,"div",7),t.ɵɵpipe(11,"translate"),t.ɵɵelementStart(12,"mat-slide-toggle",8),t.ɵɵtext(13),t.ɵɵpipe(14,"translate"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.originatorAttributesConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("hidden",!(n.originatorAttributesConfigForm.get("attributesControl").touched&&n.originatorAttributesConfigForm.get("attributesControl").hasError("atLeastOneRequired"))),t.ɵɵadvance(3),t.ɵɵproperty("labelText",t.ɵɵpipeBind1(9,5,"tb.rulenode.add-originator-attributes-to")),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(11,7,"tb.rulenode.tell-failure-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(14,9,"tb.rulenode.tell-failure")," "))},dependencies:t.ɵɵgetComponentDepsFactory(mo),encapsulation:2})}}e("OriginatorAttributesConfigComponent",mo);class uo extends i{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.originatorFields=[];for(const e of ut)this.originatorFields.push({value:e.value,name:this.translate.instant(e.name)})}configForm(){return this.originatorFieldsConfigForm}prepareOutputConfig(e){return _(e)}prepareInputConfig(e){return{dataMapping:P(e?.dataMapping)?e.dataMapping:null,ignoreNullStrings:P(e?.ignoreNullStrings)?e.ignoreNullStrings:null,fetchTo:P(e?.fetchTo)?e.fetchTo:Kt.METADATA}}onConfigurationSet(e){this.originatorFieldsConfigForm=this.fb.group({dataMapping:[e.dataMapping,[N.required]],ignoreNullStrings:[e.ignoreNullStrings,[]],fetchTo:[e.fetchTo,[]]})}static{this.ɵfac=function(e){return new(e||uo)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:uo,selectors:[["tb-enrichment-node-originator-fields-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:16,vars:32,consts:[[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],["required","","targetKeyPrefix","originator","formControlName","dataMapping","popupHelpLink","rulenode/originator_fields_node_fields_templatization",3,"selectOptions","requiredText","labelText","selectText","selectRequiredText","valText","valRequiredText","hintText"],["formControlName","fetchTo",3,"labelText"],[1,"tb-form-row","same-padding",3,"tb-hint-tooltip-icon"],["formControlName","ignoreNullStrings",1,"mat-slide","margin"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0),t.ɵɵelement(1,"tb-sv-map-config",1),t.ɵɵpipe(2,"translate"),t.ɵɵpipe(3,"translate"),t.ɵɵpipe(4,"translate"),t.ɵɵpipe(5,"translate"),t.ɵɵpipe(6,"translate"),t.ɵɵpipe(7,"translate"),t.ɵɵpipe(8,"translate"),t.ɵɵelement(9,"tb-msg-metadata-chip",2),t.ɵɵpipe(10,"translate"),t.ɵɵelementStart(11,"div",3),t.ɵɵpipe(12,"translate"),t.ɵɵelementStart(13,"mat-slide-toggle",4),t.ɵɵtext(14),t.ɵɵpipe(15,"translate"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.originatorFieldsConfigForm),t.ɵɵadvance(),t.ɵɵproperty("selectOptions",n.originatorFields)("requiredText",t.ɵɵpipeBind1(2,12,"tb.rulenode.attr-mapping-required"))("labelText",t.ɵɵpipeBind1(3,14,"tb.rulenode.originator-fields-mapping"))("selectText",t.ɵɵpipeBind1(4,16,"tb.rulenode.source-field"))("selectRequiredText",t.ɵɵpipeBind1(5,18,"tb.rulenode.source-field-required"))("valText",t.ɵɵpipeBind1(6,20,"tb.rulenode.target-key"))("valRequiredText",t.ɵɵpipeBind1(7,22,"tb.rulenode.target-key-required"))("hintText",t.ɵɵpipeBind1(8,24,"tb.rulenode.originator-fields-sv-map-hint")),t.ɵɵadvance(8),t.ɵɵproperty("labelText",t.ɵɵpipeBind1(10,26,"tb.rulenode.add-mapped-originator-fields-to")),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(12,28,"tb.rulenode.skip-empty-fields-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(15,30,"tb.rulenode.skip-empty-fields")," "))},dependencies:t.ɵɵgetComponentDepsFactory(uo),encapsulation:2})}}function co(e,n){if(1&e&&(t.ɵɵelementStart(0,"tb-toggle-option",9),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e.value),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.name," ")}}e("OriginatorFieldsConfigComponent",uo);class fo extends i{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.DataToFetch=Ft,this.msgMetadataLabelTranslations=At,this.originatorFields=[],this.fetchToData=[];for(const e of Object.keys(ut))this.originatorFields.push({value:ut[e].value,name:this.translate.instant(ut[e].name)});for(const e of qt.keys())this.fetchToData.push({value:e,name:this.translate.instant(qt.get(e))})}configForm(){return this.relatedAttributesConfigForm}prepareOutputConfig(e){e.dataToFetch===Ft.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,_(e)}prepareInputConfig(e){let t,n,r={[c.name.value]:`relatedEntity${this.translate.instant(c.name.name)}`},a={serialNumber:"sn"};return t=P(e?.telemetry)?e.telemetry?Ft.LATEST_TELEMETRY:Ft.ATTRIBUTES:P(e?.dataToFetch)?e.dataToFetch:Ft.ATTRIBUTES,n=P(e?.attrMapping)?e.attrMapping:P(e?.dataMapping)?e.dataMapping:null,t===Ft.FIELDS?r=n:a=n,{relationsQuery:P(e?.relationsQuery)?e.relationsQuery:null,dataToFetch:t,svMap:r,kvMap:a,fetchTo:P(e?.fetchTo)?e.fetchTo:Kt.METADATA}}selectTranslation(e,t){return this.relatedAttributesConfigForm.get("dataToFetch").value===Ft.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.relatedAttributesConfigForm=this.fb.group({relationsQuery:[e.relationsQuery,[N.required]],dataToFetch:[e.dataToFetch,[]],kvMap:[e.kvMap,[N.required]],svMap:[e.svMap,[N.required]],fetchTo:[e.fetchTo,[]]})}validatorTriggers(){return["dataToFetch"]}updateValidators(e){this.relatedAttributesConfigForm.get("dataToFetch").value===Ft.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())}static{this.ɵfac=function(e){return new(e||fo)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:fo,selectors:[["tb-enrichment-node-related-attributes-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:24,vars:48,consts:[[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],["required","","formControlName","relationsQuery"],[1,"tb-form-panel","stroked"],["translate","",1,"tb-form-panel-title"],["formControlName","dataToFetch","appearance","fill"],[3,"value",4,"ngFor","ngForOf"],["required","","formControlName","kvMap","popupHelpLink","rulenode/related_entity_data_node_fields_templatization",3,"hidden","requiredText","labelText","keyText","keyRequiredText","valText","valRequiredText","hintText"],["required","","targetKeyPrefix","relatedEntity","formControlName","svMap","popupHelpLink","rulenode/related_entity_data_node_fields_templatization",3,"hidden","labelText","selectOptions","requiredText","selectText","selectRequiredText","valText","valRequiredText","hintText"],["formControlName","fetchTo",3,"labelText"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0),t.ɵɵelement(1,"tb-relations-query-config",1),t.ɵɵelementStart(2,"div",2)(3,"div",3),t.ɵɵtext(4,"tb.rulenode.data-to-fetch"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"tb-toggle-select",4),t.ɵɵtemplate(6,co,2,2,"tb-toggle-option",5),t.ɵɵelementEnd(),t.ɵɵelement(7,"tb-kv-map-config",6),t.ɵɵpipe(8,"translate"),t.ɵɵpipe(9,"translate"),t.ɵɵpipe(10,"translate"),t.ɵɵpipe(11,"translate"),t.ɵɵpipe(12,"translate"),t.ɵɵpipe(13,"translate"),t.ɵɵelement(14,"tb-sv-map-config",7),t.ɵɵpipe(15,"translate"),t.ɵɵpipe(16,"translate"),t.ɵɵpipe(17,"translate"),t.ɵɵpipe(18,"translate"),t.ɵɵpipe(19,"translate"),t.ɵɵpipe(20,"translate"),t.ɵɵpipe(21,"translate"),t.ɵɵelement(22,"tb-msg-metadata-chip",8),t.ɵɵpipe(23,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.relatedAttributesConfigForm),t.ɵɵadvance(6),t.ɵɵproperty("ngForOf",n.fetchToData),t.ɵɵadvance(),t.ɵɵproperty("hidden",n.relatedAttributesConfigForm.get("dataToFetch").value===n.DataToFetch.FIELDS)("requiredText",t.ɵɵpipeBind1(8,20,"tb.rulenode.attr-mapping-required"))("labelText",t.ɵɵpipeBind1(9,22,n.selectTranslation("tb.rulenode.latest-telemetry-mapping","tb.rulenode.attributes-mapping")))("keyText",t.ɵɵpipeBind1(10,24,n.selectTranslation("tb.rulenode.source-telemetry","tb.rulenode.source-attribute")))("keyRequiredText",t.ɵɵpipeBind1(11,26,n.selectTranslation("tb.rulenode.source-telemetry-required","tb.rulenode.source-attribute-required")))("valText",t.ɵɵpipeBind1(12,28,"tb.rulenode.target-key"))("valRequiredText",t.ɵɵpipeBind1(13,30,"tb.rulenode.target-key-required"))("hintText","tb.rulenode.kv-map-pattern-hint"),t.ɵɵadvance(7),t.ɵɵproperty("hidden",n.relatedAttributesConfigForm.get("dataToFetch").value!==n.DataToFetch.FIELDS)("labelText",t.ɵɵpipeBind1(15,32,"tb.rulenode.fields-mapping"))("selectOptions",n.originatorFields)("requiredText",t.ɵɵpipeBind1(16,34,"tb.rulenode.attr-mapping-required"))("selectText",t.ɵɵpipeBind1(17,36,"tb.rulenode.source-field"))("selectRequiredText",t.ɵɵpipeBind1(18,38,"tb.rulenode.source-field-required"))("valText",t.ɵɵpipeBind1(19,40,"tb.rulenode.target-key"))("valRequiredText",t.ɵɵpipeBind1(20,42,"tb.rulenode.target-key-required"))("hintText",t.ɵɵpipeBind1(21,44,"tb.rulenode.sv-map-hint")),t.ɵɵadvance(8),t.ɵɵproperty("labelText",t.ɵɵpipeBind1(23,46,n.msgMetadataLabelTranslations.get(n.relatedAttributesConfigForm.get("dataToFetch").value))))},dependencies:t.ɵɵgetComponentDepsFactory(fo),encapsulation:2})}}function go(e,n){if(1&e&&(t.ɵɵelementStart(0,"tb-toggle-option",8),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e.value),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.name," ")}}e("RelatedAttributesConfigComponent",fo);class ho extends i{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.fetchToData=[],this.DataToFetch=Ft;for(const e of qt.keys())e!==Ft.FIELDS&&this.fetchToData.push({value:e,name:this.translate.instant(qt.get(e))})}configForm(){return this.tenantAttributesConfigForm}prepareInputConfig(e){let t,n;return t=P(e?.telemetry)?e.telemetry?Ft.LATEST_TELEMETRY:Ft.ATTRIBUTES:P(e?.dataToFetch)?e.dataToFetch:Ft.ATTRIBUTES,n=P(e?.attrMapping)?e.attrMapping:P(e?.dataMapping)?e.dataMapping:null,{dataToFetch:t,dataMapping:n,fetchTo:P(e?.fetchTo)?e.fetchTo:Kt.METADATA}}selectTranslation(e,t){return this.tenantAttributesConfigForm.get("dataToFetch").value===Ft.LATEST_TELEMETRY?e:t}onConfigurationSet(e){this.tenantAttributesConfigForm=this.fb.group({dataToFetch:[e.dataToFetch,[]],dataMapping:[e.dataMapping,[N.required]],fetchTo:[e.fetchTo,[]]})}static{this.ɵfac=function(e){return new(e||ho)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:ho,selectors:[["tb-enrichment-node-tenant-attributes-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:17,vars:26,consts:[[1,"tb-form-panel","stroked",3,"formGroup"],["translate","",1,"tb-form-panel-title"],[1,"flex","flex-1","items-center","justify-center"],[1,"fetch-to-data-toggle"],["formControlName","dataToFetch","appearance","fill",1,"fetch-to-data-toggle"],[3,"value",4,"ngFor","ngForOf"],["required","","formControlName","dataMapping","popupHelpLink","rulenode/tenant_attributes_node_fields_templatization",3,"requiredText","labelText","keyText","keyRequiredText","valText","valRequiredText","hintText"],["formControlName","fetchTo",3,"labelText"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵtext(2,"tb.rulenode.mapping-of-tenant"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"div",2)(4,"div",3)(5,"tb-toggle-select",4),t.ɵɵtemplate(6,go,2,2,"tb-toggle-option",5),t.ɵɵelementEnd()()(),t.ɵɵelement(7,"tb-kv-map-config",6),t.ɵɵpipe(8,"translate"),t.ɵɵpipe(9,"translate"),t.ɵɵpipe(10,"translate"),t.ɵɵpipe(11,"translate"),t.ɵɵpipe(12,"translate"),t.ɵɵpipe(13,"translate"),t.ɵɵelement(14,"tb-msg-metadata-chip",7),t.ɵɵpipe(15,"translate"),t.ɵɵpipe(16,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.tenantAttributesConfigForm),t.ɵɵadvance(6),t.ɵɵproperty("ngForOf",n.fetchToData),t.ɵɵadvance(),t.ɵɵproperty("requiredText",t.ɵɵpipeBind1(8,10,"tb.rulenode.attr-mapping-required"))("labelText",t.ɵɵpipeBind1(9,12,n.selectTranslation("tb.rulenode.latest-telemetry-mapping","tb.rulenode.attributes-mapping")))("keyText",t.ɵɵpipeBind1(10,14,n.selectTranslation("tb.rulenode.source-telemetry","tb.rulenode.source-attribute")))("keyRequiredText",t.ɵɵpipeBind1(11,16,n.selectTranslation("tb.rulenode.source-telemetry-required","tb.rulenode.source-attribute-required")))("valText",t.ɵɵpipeBind1(12,18,"tb.rulenode.target-key"))("valRequiredText",t.ɵɵpipeBind1(13,20,"tb.rulenode.target-key-required"))("hintText","tb.rulenode.kv-map-pattern-hint"),t.ɵɵadvance(7),t.ɵɵproperty("labelText",n.tenantAttributesConfigForm.get("dataToFetch").value===n.DataToFetch.LATEST_TELEMETRY?t.ɵɵpipeBind1(15,22,"tb.rulenode.add-mapped-latest-telemetry-to"):t.ɵɵpipeBind1(16,24,"tb.rulenode.add-mapped-attribute-to")))},dependencies:t.ɵɵgetComponentDepsFactory(ho),styles:["[_nghost-%COMP%] .fetch-to-data-toggle[_ngcontent-%COMP%]{max-width:420px;width:100%}"]})}}e("TenantAttributesConfigComponent",ho);class yo extends i{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.fetchDeviceCredentialsConfigForm}prepareInputConfig(e){return{fetchTo:P(e?.fetchTo)?e.fetchTo:Kt.METADATA}}onConfigurationSet(e){this.fetchDeviceCredentialsConfigForm=this.fb.group({fetchTo:[e.fetchTo,[]]})}static{this.ɵfac=function(e){return new(e||yo)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:yo,selectors:[["tb-enrichment-node-fetch-device-credentials-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:3,vars:4,consts:[[3,"formGroup"],["formControlName","fetchTo",3,"labelText"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0),t.ɵɵelement(1,"tb-msg-metadata-chip",1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.fetchDeviceCredentialsConfigForm),t.ɵɵadvance(),t.ɵɵproperty("labelText",t.ɵɵpipeBind1(2,2,"tb.rulenode.fetch-credentials-to")))},dependencies:t.ɵɵgetComponentDepsFactory(yo),encapsulation:2})}}e("FetchDeviceCredentialsConfigComponent",yo);class bo{static{this.ɵfac=function(e){return new(e||bo)}}static{this.ɵmod=t.ɵɵdefineNgModule({type:bo})}static{this.ɵinj=t.ɵɵdefineInjector({imports:[$,S,xi,Vi,Li,Oi,mo,uo,po,fo,ho,Mi,yo]})}}function vo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.topic-required")," "))}function xo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.hostname-required")," "))}function Co(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.device-id-required")," "))}function So(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",17),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.azureIotHubCredentialsTypeTranslationsMap.get(e))," ")}}function To(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.credentials-type-required")," "))}function Io(e,t){}function Eo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.sas-key-required")," "))}function Fo(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"mat-form-field",5)(1,"mat-label",2),t.ɵɵtext(2,"tb.rulenode.sas-key"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",18)(4,"tb-toggle-password",19),t.ɵɵtemplate(5,Eo,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(6,"tb-file-input",20),t.ɵɵpipe(7,"translate"),t.ɵɵpipe(8,"translate"),t.ɵɵlistener("fileNameChanged",(function(n){t.ɵɵrestoreView(e);const r=t.ɵɵnextContext();return t.ɵɵresetView(r.azureIotHubConfigForm.get("credentials.caCertFileName").setValue(n))})),t.ɵɵelementEnd()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(5),t.ɵɵproperty("ngIf",e.azureIotHubConfigForm.get("credentials.sasKey").hasError("required")),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("label",t.ɵɵpipeBind1(7,4,"tb.rulenode.azure-ca-cert")),t.ɵɵpropertyInterpolate("dropLabel",t.ɵɵpipeBind1(8,6,"tb.rulenode.drop-file")),t.ɵɵproperty("existingFileName",e.azureIotHubConfigForm.get("credentials.caCertFileName").value)}}function qo(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-file-input",20),t.ɵɵpipe(1,"translate"),t.ɵɵpipe(2,"translate"),t.ɵɵlistener("fileNameChanged",(function(n){t.ɵɵrestoreView(e);const r=t.ɵɵnextContext();return t.ɵɵresetView(r.azureIotHubConfigForm.get("credentials.caCertFileName").setValue(n))})),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"tb-file-input",21),t.ɵɵpipe(4,"translate"),t.ɵɵpipe(5,"translate"),t.ɵɵlistener("fileNameChanged",(function(n){t.ɵɵrestoreView(e);const r=t.ɵɵnextContext();return t.ɵɵresetView(r.azureIotHubConfigForm.get("credentials.certFileName").setValue(n))})),t.ɵɵelementEnd(),t.ɵɵelementStart(6,"tb-file-input",22),t.ɵɵpipe(7,"translate"),t.ɵɵpipe(8,"translate"),t.ɵɵlistener("fileNameChanged",(function(n){t.ɵɵrestoreView(e);const r=t.ɵɵnextContext();return t.ɵɵresetView(r.azureIotHubConfigForm.get("credentials.privateKeyFileName").setValue(n))})),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"mat-form-field",5)(10,"mat-label",2),t.ɵɵtext(11,"tb.rulenode.private-key-password"),t.ɵɵelementEnd(),t.ɵɵelement(12,"input",23)(13,"tb-toggle-password",19),t.ɵɵelementEnd()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵpropertyInterpolate("label",t.ɵɵpipeBind1(1,9,"tb.rulenode.azure-ca-cert")),t.ɵɵpropertyInterpolate("dropLabel",t.ɵɵpipeBind1(2,11,"tb.rulenode.drop-file")),t.ɵɵproperty("existingFileName",e.azureIotHubConfigForm.get("credentials.caCertFileName").value),t.ɵɵadvance(3),t.ɵɵpropertyInterpolate("label",t.ɵɵpipeBind1(4,13,"tb.rulenode.cert")),t.ɵɵpropertyInterpolate("dropLabel",t.ɵɵpipeBind1(5,15,"tb.rulenode.drop-file")),t.ɵɵproperty("existingFileName",e.azureIotHubConfigForm.get("credentials.certFileName").value),t.ɵɵadvance(3),t.ɵɵpropertyInterpolate("label",t.ɵɵpipeBind1(7,17,"tb.rulenode.private-key")),t.ɵɵpropertyInterpolate("dropLabel",t.ɵɵpipeBind1(8,19,"tb.rulenode.drop-file")),t.ɵɵproperty("existingFileName",e.azureIotHubConfigForm.get("credentials.privateKeyFileName").value)}}e("RulenodeCoreConfigEnrichmentModule",bo),("undefined"==typeof ngJitMode||ngJitMode)&&t.ɵɵsetNgModuleScope(bo,{declarations:[Vi,Li,Oi,mo,uo,po,fo,ho,Mi,yo],imports:[$,S,xi],exports:[Vi,Li,Oi,mo,uo,po,fo,ho,Mi,yo]});class Ao extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.allAzureIotHubCredentialsTypes=Vt,this.azureIotHubCredentialsTypeTranslationsMap=Ot}configForm(){return this.azureIotHubConfigForm}onConfigurationSet(e){this.azureIotHubConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[N.required]],host:[e?e.host:null,[N.required]],port:[e?e.port:null,[N.required,N.min(1),N.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[N.required,N.min(1),N.max(200)]],clientId:[e?e.clientId:null,[N.required]],cleanSession:[!!e&&e.cleanSession,[]],ssl:[!!e&&e.ssl,[]],credentials:this.fb.group({type:[e&&e.credentials?e.credentials.type:null,[N.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([N.required]);break;case"cert.PEM":t.get("privateKey").setValidators([N.required]),t.get("privateKeyFileName").setValidators([N.required]),t.get("cert").setValidators([N.required]),t.get("certFileName").setValidators([N.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})}static{this.ɵfac=function(e){return new(e||Ao)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Ao,selectors:[["tb-external-node-azure-iot-hub-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:37,vars:10,consts:[[1,"flex","flex-col",3,"formGroup"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","topicPattern"],[4,"ngIf"],[1,"mat-block"],["required","","matInput","","formControlName","host"],["required","","matInput","","formControlName","clientId","autocomplete","new-clientId"],[1,"tb-mqtt-credentials-panel-group"],["translate","",1,"tb-required"],["formGroupName","credentials",1,"flex","flex-col"],["formControlName","type","required",""],[3,"value",4,"ngFor","ngForOf"],[1,"flex","flex-col",3,"ngSwitch"],["ngSwitchCase","anonymous"],["ngSwitchCase","sas"],["ngSwitchCase","cert.PEM"],[3,"value"],["type","password","required","","matInput","","formControlName","sasKey","autocomplete","new-password"],["matSuffix",""],["formControlName","caCert","inputId","caCertSelect","noFileText","tb.rulenode.no-file",3,"fileNameChanged","existingFileName","label","dropLabel"],["formControlName","cert","inputId","CertSelect","required","","requiredAsError","","noFileText","tb.rulenode.no-file",3,"fileNameChanged","existingFileName","label","dropLabel"],["formControlName","privateKey","inputId","privateKeySelect","required","","requiredAsError","","noFileText","tb.rulenode.no-file",2,"padding-bottom","8px",3,"fileNameChanged","existingFileName","label","dropLabel"],["type","password","matInput","","formControlName","password","autocomplete","new-password"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.topic"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,vo,3,3,"mat-error",4),t.ɵɵelementStart(6,"mat-hint",2),t.ɵɵtext(7,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(8,"mat-form-field",5)(9,"mat-label",2),t.ɵɵtext(10,"tb.rulenode.hostname"),t.ɵɵelementEnd(),t.ɵɵelement(11,"input",6),t.ɵɵtemplate(12,xo,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(13,"mat-form-field",5)(14,"mat-label",2),t.ɵɵtext(15,"tb.rulenode.device-id"),t.ɵɵelementEnd(),t.ɵɵelement(16,"input",7),t.ɵɵtemplate(17,Co,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(18,"mat-accordion")(19,"mat-expansion-panel",8)(20,"mat-expansion-panel-header")(21,"mat-panel-title",9),t.ɵɵtext(22,"tb.rulenode.credentials"),t.ɵɵelementEnd(),t.ɵɵelementStart(23,"mat-panel-description"),t.ɵɵtext(24),t.ɵɵpipe(25,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(26,"section",10)(27,"mat-form-field",5)(28,"mat-label",2),t.ɵɵtext(29,"tb.rulenode.credentials-type"),t.ɵɵelementEnd(),t.ɵɵelementStart(30,"mat-select",11),t.ɵɵtemplate(31,So,3,4,"mat-option",12),t.ɵɵelementEnd(),t.ɵɵtemplate(32,To,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(33,"section",13),t.ɵɵtemplate(34,Io,0,0,"ng-template",14)(35,Fo,9,8,"ng-template",15)(36,qo,14,21,"ng-template",16),t.ɵɵelementEnd()()()()()),2&e&&(t.ɵɵproperty("formGroup",n.azureIotHubConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.azureIotHubConfigForm.get("topicPattern").hasError("required")),t.ɵɵadvance(7),t.ɵɵproperty("ngIf",n.azureIotHubConfigForm.get("host").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.azureIotHubConfigForm.get("clientId").hasError("required")),t.ɵɵadvance(7),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(25,8,n.azureIotHubCredentialsTypeTranslationsMap.get(n.azureIotHubConfigForm.get("credentials.type").value))," "),t.ɵɵadvance(7),t.ɵɵproperty("ngForOf",n.allAzureIotHubCredentialsTypes),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.azureIotHubConfigForm.get("credentials.type").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngSwitch",n.azureIotHubConfigForm.get("credentials.type").value))},dependencies:t.ɵɵgetComponentDepsFactory(Ao),styles:["[_nghost-%COMP%] .tb-mqtt-credentials-panel-group[_ngcontent-%COMP%]{margin:0 6px}"]})}}function ko(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.topic-pattern-required")," "))}function No(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.bootstrap-servers-required")," "))}function wo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-retries-message")," "))}function Mo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-batch-size-bytes-message")," "))}function Bo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-linger-ms-message")," "))}function Vo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-buffer-memory-bytes-message")," "))}function Oo(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",21),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e," ")}}function Do(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.key-serializer-required")," "))}function Lo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.value-serializer-required")," "))}function Po(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",21),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.ToByteStandartCharsetTypeTranslationMap.get(e))," ")}}function Ro(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",22)(1,"mat-label",2),t.ɵɵtext(2,"tb.rulenode.charset-encoding"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"mat-select",23),t.ɵɵtemplate(4,Po,3,4,"mat-option",14),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵproperty("ngForOf",e.ToByteStandartCharsetTypesValues)}}e("AzureIotHubConfigComponent",Ao);class _o extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.ackValues=["all","-1","0","1"],this.ToByteStandartCharsetTypesValues=Lt,this.ToByteStandartCharsetTypeTranslationMap=Pt}configForm(){return this.kafkaConfigForm}onConfigurationSet(e){this.kafkaConfigForm=this.fb.group({topicPattern:[e?e.topicPattern:null,[N.required]],keyPattern:[e?e.keyPattern:null],bootstrapServers:[e?e.bootstrapServers:null,[N.required]],retries:[e?e.retries:null,[N.min(0)]],batchSize:[e?e.batchSize:null,[N.min(0)]],linger:[e?e.linger:null,[N.min(0)]],bufferMemory:[e?e.bufferMemory:null,[N.min(0)]],acks:[e?e.acks:null,[N.required]],keySerializer:[e?e.keySerializer:null,[N.required]],valueSerializer:[e?e.valueSerializer:null,[N.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([N.required]):this.kafkaConfigForm.get("kafkaHeadersCharset").setValidators([]),this.kafkaConfigForm.get("kafkaHeadersCharset").updateValueAndValidity({emitEvent:e})}static{this.ɵfac=function(e){return new(e||_o)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:_o,selectors:[["tb-external-node-kafka-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:65,vars:14,consts:[[1,"flex","flex-col",3,"formGroup"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","topicPattern"],[4,"ngIf"],["matInput","","formControlName","keyPattern"],["translate","",1,"tb-hint"],[1,"mat-block"],["required","","matInput","","formControlName","bootstrapServers"],["type","number","step","1","min","0","matInput","","formControlName","retries"],["type","number","step","1","min","0","matInput","","formControlName","batchSize"],["type","number","step","1","min","0","matInput","","formControlName","linger"],["type","number","step","1","min","0","matInput","","formControlName","bufferMemory"],["formControlName","acks","required",""],[3,"value",4,"ngFor","ngForOf"],["required","","matInput","","formControlName","keySerializer"],["required","","matInput","","formControlName","valueSerializer"],["translate","",1,"tb-title"],["required","false","formControlName","otherProperties","keyText","tb.rulenode.key","keyRequiredText","tb.rulenode.key-required","valText","tb.rulenode.value","valRequiredText","tb.rulenode.value-required"],["formControlName","addMetadataKeyValuesAsKafkaHeaders",1,"flex-1"],["class","mat-block flex-1",4,"ngIf"],[3,"value"],[1,"mat-block","flex-1"],["formControlName","kafkaHeadersCharset","required",""]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.topic-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,ko,3,3,"mat-error",4),t.ɵɵelementStart(6,"mat-hint",2),t.ɵɵtext(7,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(8,"mat-form-field",1)(9,"mat-label",2),t.ɵɵtext(10,"tb.rulenode.key-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(11,"input",5),t.ɵɵelementStart(12,"mat-hint",2),t.ɵɵtext(13,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(14,"div",6),t.ɵɵtext(15,"tb.rulenode.key-pattern-hint"),t.ɵɵelementEnd(),t.ɵɵelementStart(16,"mat-form-field",7)(17,"mat-label",2),t.ɵɵtext(18,"tb.rulenode.bootstrap-servers"),t.ɵɵelementEnd(),t.ɵɵelement(19,"input",8),t.ɵɵtemplate(20,No,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(21,"mat-form-field",7)(22,"mat-label",2),t.ɵɵtext(23,"tb.rulenode.retries"),t.ɵɵelementEnd(),t.ɵɵelement(24,"input",9),t.ɵɵtemplate(25,wo,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(26,"mat-form-field",7)(27,"mat-label",2),t.ɵɵtext(28,"tb.rulenode.batch-size-bytes"),t.ɵɵelementEnd(),t.ɵɵelement(29,"input",10),t.ɵɵtemplate(30,Mo,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(31,"mat-form-field",7)(32,"mat-label",2),t.ɵɵtext(33,"tb.rulenode.linger-ms"),t.ɵɵelementEnd(),t.ɵɵelement(34,"input",11),t.ɵɵtemplate(35,Bo,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(36,"mat-form-field",7)(37,"mat-label",2),t.ɵɵtext(38,"tb.rulenode.buffer-memory-bytes"),t.ɵɵelementEnd(),t.ɵɵelement(39,"input",12),t.ɵɵtemplate(40,Vo,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(41,"mat-form-field",7)(42,"mat-label",2),t.ɵɵtext(43,"tb.rulenode.acks"),t.ɵɵelementEnd(),t.ɵɵelementStart(44,"mat-select",13),t.ɵɵtemplate(45,Oo,2,2,"mat-option",14),t.ɵɵelementEnd()(),t.ɵɵelementStart(46,"mat-form-field",7)(47,"mat-label",2),t.ɵɵtext(48,"tb.rulenode.key-serializer"),t.ɵɵelementEnd(),t.ɵɵelement(49,"input",15),t.ɵɵtemplate(50,Do,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(51,"mat-form-field",7)(52,"mat-label",2),t.ɵɵtext(53,"tb.rulenode.value-serializer"),t.ɵɵelementEnd(),t.ɵɵelement(54,"input",16),t.ɵɵtemplate(55,Lo,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(56,"label",17),t.ɵɵtext(57,"tb.rulenode.other-properties"),t.ɵɵelementEnd(),t.ɵɵelement(58,"tb-kv-map-config-old",18),t.ɵɵelementStart(59,"mat-checkbox",19),t.ɵɵtext(60),t.ɵɵpipe(61,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(62,"div",6),t.ɵɵtext(63,"tb.rulenode.add-metadata-key-values-as-kafka-headers-hint"),t.ɵɵelementEnd(),t.ɵɵtemplate(64,Ro,5,1,"mat-form-field",20),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.kafkaConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.kafkaConfigForm.get("topicPattern").hasError("required")),t.ɵɵadvance(15),t.ɵɵproperty("ngIf",n.kafkaConfigForm.get("bootstrapServers").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.kafkaConfigForm.get("retries").hasError("min")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.kafkaConfigForm.get("batchSize").hasError("min")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.kafkaConfigForm.get("linger").hasError("min")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.kafkaConfigForm.get("bufferMemory").hasError("min")),t.ɵɵadvance(5),t.ɵɵproperty("ngForOf",n.ackValues),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.kafkaConfigForm.get("keySerializer").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.kafkaConfigForm.get("valueSerializer").hasError("required")),t.ɵɵadvance(5),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(61,12,"tb.rulenode.add-metadata-key-values-as-kafka-headers")," "),t.ɵɵadvance(4),t.ɵɵproperty("ngIf",n.kafkaConfigForm.get("addMetadataKeyValuesAsKafkaHeaders").value))},dependencies:t.ɵɵgetComponentDepsFactory(_o),encapsulation:2})}}function jo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.topic-pattern-required")," "))}function Go(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.host-required")," "))}function Ko(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.port-required")," "))}function Uo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.port-range")," "))}function Ho(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.port-range")," "))}function zo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.connect-timeout-required")," "))}function $o(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.connect-timeout-range")," "))}function Qo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.connect-timeout-range")," "))}e("KafkaConfigComponent",_o);class Jo extends i{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,[N.required]],host:[e?e.host:null,[N.required]],port:[e?e.port:null,[N.required,N.min(1),N.max(65535)]],connectTimeoutSec:[e?e.connectTimeoutSec:null,[N.required,N.min(1),N.max(200)]],clientId:[e?e.clientId:null,[]],appendClientIdSuffix:[{value:!!e&&e.appendClientIdSuffix,disabled:!(e&&G(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){G(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"]}static{this.ɵfac=function(e){return new(e||Jo)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Jo,selectors:[["tb-external-node-mqtt-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:57,vars:34,consts:[[1,"flex","flex-col",3,"formGroup"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","topicPattern"],[4,"ngIf"],[1,"flex","flex-1","flex-col","gt-sm:flex-row","gt-sm:gap-2"],[1,"mat-block","gt-sm:max-w-60%","gt-sm:flex-full"],["required","","matInput","","formControlName","host"],[1,"mat-block","gt-sm:max-w-40%","gt-sm:flex-full"],["required","","type","number","step","1","min","1","max","65535","matInput","","formControlName","port"],["required","","type","number","step","1","min","1","max","200","matInput","","formControlName","connectTimeoutSec"],["matInput","","formControlName","clientId"],["formControlName","appendClientIdSuffix"],[1,"tb-hint"],["formControlName","parseToPlainText"],["formControlName","cleanSession"],["formControlName","retainedMessage"],["formControlName","ssl"],["formControlName","credentials",3,"passwordFieldRequired"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.topic-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,jo,3,3,"mat-error",4),t.ɵɵelementStart(6,"mat-hint",2),t.ɵɵtext(7,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(8,"div",5)(9,"mat-form-field",6)(10,"mat-label",2),t.ɵɵtext(11,"tb.rulenode.host"),t.ɵɵelementEnd(),t.ɵɵelement(12,"input",7),t.ɵɵtemplate(13,Go,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(14,"mat-form-field",8)(15,"mat-label",2),t.ɵɵtext(16,"tb.rulenode.port"),t.ɵɵelementEnd(),t.ɵɵelement(17,"input",9),t.ɵɵtemplate(18,Ko,3,3,"mat-error",4)(19,Uo,3,3,"mat-error",4)(20,Ho,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(21,"mat-form-field",8)(22,"mat-label",2),t.ɵɵtext(23,"tb.rulenode.connect-timeout"),t.ɵɵelementEnd(),t.ɵɵelement(24,"input",10),t.ɵɵtemplate(25,zo,3,3,"mat-error",4)(26,$o,3,3,"mat-error",4)(27,Qo,3,3,"mat-error",4),t.ɵɵelementEnd()(),t.ɵɵelementStart(28,"mat-form-field",1)(29,"mat-label",2),t.ɵɵtext(30,"tb.rulenode.client-id"),t.ɵɵelementEnd(),t.ɵɵelement(31,"input",11),t.ɵɵelementStart(32,"mat-hint"),t.ɵɵtext(33),t.ɵɵpipe(34,"translate"),t.ɵɵelementEnd()(),t.ɵɵelementStart(35,"mat-checkbox",12),t.ɵɵtext(36),t.ɵɵpipe(37,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(38,"div",13),t.ɵɵtext(39),t.ɵɵpipe(40,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(41,"mat-checkbox",14),t.ɵɵtext(42),t.ɵɵpipe(43,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(44,"div",13),t.ɵɵtext(45),t.ɵɵpipe(46,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(47,"mat-checkbox",15),t.ɵɵtext(48),t.ɵɵpipe(49,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(50,"mat-checkbox",16),t.ɵɵtext(51),t.ɵɵpipe(52,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(53,"mat-checkbox",17),t.ɵɵtext(54),t.ɵɵpipe(55,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(56,"tb-credentials-config",18),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.mqttConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.mqttConfigForm.get("topicPattern").hasError("required")),t.ɵɵadvance(8),t.ɵɵproperty("ngIf",n.mqttConfigForm.get("host").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.mqttConfigForm.get("port").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.mqttConfigForm.get("port").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.mqttConfigForm.get("port").hasError("max")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.mqttConfigForm.get("connectTimeoutSec").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.mqttConfigForm.get("connectTimeoutSec").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.mqttConfigForm.get("connectTimeoutSec").hasError("max")),t.ɵɵadvance(6),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(34,18,"tb.rulenode.client-id-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(37,20,"tb.rulenode.append-client-id-suffix")," "),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(40,22,"tb.rulenode.client-id-suffix-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(43,24,"tb.rulenode.parse-to-plain-text")," "),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(46,26,"tb.rulenode.parse-to-plain-text-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(49,28,"tb.rulenode.clean-session")," "),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(52,30,"tb.rulenode.retained-message")," "),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(55,32,"tb.rulenode.enable-ssl")," "),t.ɵɵadvance(2),t.ɵɵproperty("passwordFieldRequired",!1))},dependencies:t.ɵɵgetComponentDepsFactory(Jo),styles:["[_nghost-%COMP%] .tb-mqtt-credentials-panel-group[_ngcontent-%COMP%]{margin:0 6px}"]})}}e("MqttConfigComponent",Jo);class Yo extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.notificationType=E,this.entityType=u}configForm(){return this.notificationConfigForm}onConfigurationSet(e){this.notificationConfigForm=this.fb.group({templateId:[e?e.templateId:null,[N.required]],targets:[e?e.targets:[],[N.required]]})}static{this.ɵfac=function(e){return new(e||Yo)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Yo,selectors:[["tb-external-node-notification-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:6,vars:13,consts:[[1,"flex","flex-col",3,"formGroup"],["required","","allowCreate","","formControlName","templateId",3,"notificationTypes"],["required","","formControlName","targets",3,"labelText","placeholderText","requiredText","entityType","subType"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0),t.ɵɵelement(1,"tb-template-autocomplete",1)(2,"tb-entity-list",2),t.ɵɵpipe(3,"translate"),t.ɵɵpipe(4,"translate"),t.ɵɵpipe(5,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.notificationConfigForm),t.ɵɵadvance(),t.ɵɵproperty("notificationTypes",n.notificationType.RULE_NODE),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("labelText",t.ɵɵpipeBind1(3,7,"notification.recipients")),t.ɵɵpropertyInterpolate("placeholderText",t.ɵɵpipeBind1(4,9,"notification.recipient")),t.ɵɵpropertyInterpolate("requiredText",t.ɵɵpipeBind1(5,11,"notification.recipients-required")),t.ɵɵpropertyInterpolate("entityType",n.entityType.NOTIFICATION_TARGET),t.ɵɵpropertyInterpolate("subType",n.notificationType.RULE_NODE))},dependencies:t.ɵɵgetComponentDepsFactory(Yo),encapsulation:2})}}function Wo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.gcp-project-id-required")," "))}function Xo(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.pubsub-topic-name-required")," "))}e("NotificationConfigComponent",Yo);class Zo extends i{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,[N.required]],topicName:[e?e.topicName:null,[N.required]],serviceAccountKey:[e?e.serviceAccountKey:null,[N.required]],serviceAccountKeyFileName:[e?e.serviceAccountKeyFileName:null,[N.required]],messageAttributes:[e?e.messageAttributes:null,[]]})}static{this.ɵfac=function(e){return new(e||Zo)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Zo,selectors:[["tb-external-node-pub-sub-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:20,vars:16,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"mat-block"],["translate",""],["required","","matInput","","formControlName","projectId"],[4,"ngIf"],["required","","matInput","","formControlName","topicName"],["formControlName","serviceAccountKey","required","","requiredAsError","","noFileText","tb.rulenode.no-file",2,"padding-bottom","24px",3,"fileNameChanged","existingFileName","label","dropLabel"],["translate","",1,"tb-title"],[1,"tb-hint",3,"innerHTML"],["required","false","formControlName","messageAttributes","keyText","tb.rulenode.name","keyRequiredText","tb.rulenode.name-required","valText","tb.rulenode.value","valRequiredText","tb.rulenode.value-required"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.gcp-project-id"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,Wo,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(6,"mat-form-field",1)(7,"mat-label",2),t.ɵɵtext(8,"tb.rulenode.pubsub-topic-name"),t.ɵɵelementEnd(),t.ɵɵelement(9,"input",5),t.ɵɵtemplate(10,Xo,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(11,"tb-file-input",6),t.ɵɵpipe(12,"translate"),t.ɵɵpipe(13,"translate"),t.ɵɵlistener("fileNameChanged",(function(e){return n.pubSubConfigForm.get("serviceAccountKeyFileName").setValue(e)})),t.ɵɵelementEnd(),t.ɵɵelementStart(14,"label",7),t.ɵɵtext(15,"tb.rulenode.message-attributes"),t.ɵɵelementEnd(),t.ɵɵelement(16,"div",8),t.ɵɵpipe(17,"translate"),t.ɵɵpipe(18,"safe"),t.ɵɵelement(19,"tb-kv-map-config-old",9),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.pubSubConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.pubSubConfigForm.get("projectId").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.pubSubConfigForm.get("topicName").hasError("required")),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("label",t.ɵɵpipeBind1(12,7,"tb.rulenode.gcp-service-account-key")),t.ɵɵpropertyInterpolate("dropLabel",t.ɵɵpipeBind1(13,9,"tb.rulenode.drop-file")),t.ɵɵproperty("existingFileName",n.pubSubConfigForm.get("serviceAccountKeyFileName").value),t.ɵɵadvance(5),t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(18,13,t.ɵɵpipeBind1(17,11,"tb.rulenode.message-attributes-hint"),"html"),t.ɵɵsanitizeHtml))},dependencies:t.ɵɵgetComponentDepsFactory(Zo),encapsulation:2})}}function el(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",22),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e," ")}}function tl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.host-required")," "))}function nl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.port-required")," "))}function rl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.port-range")," "))}function al(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.port-range")," "))}function il(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-connection-timeout-ms-message")," "))}function ol(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-handshake-timeout-ms-message")," "))}e("PubSubConfigComponent",Zo);class ll extends i{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,[N.required]],port:[e?e.port:null,[N.required,N.min(1),N.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,[N.min(0)]],handshakeTimeout:[e?e.handshakeTimeout:null,[N.min(0)]],clientProperties:[e?e.clientProperties:null,[]]})}static{this.ɵfac=function(e){return new(e||ll)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:ll,selectors:[["tb-external-node-rabbit-mq-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:56,vars:11,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"mat-block"],["translate",""],["matInput","","formControlName","exchangeNamePattern"],["matInput","","formControlName","routingKeyPattern"],["formControlName","messageProperties"],[3,"value",4,"ngFor","ngForOf"],[1,"gt-sm:flex","gt-sm:flex-row","gt-sm:gap-2"],[1,"mat-block","gt-sm:max-w-60%","gt-sm:flex-full"],["required","","matInput","","formControlName","host"],[4,"ngIf"],[1,"mat-block","gt-sm:max-w-40%","gt-sm:flex-full"],["required","","type","number","step","1","min","1","max","65535","matInput","","formControlName","port"],["matInput","","formControlName","virtualHost"],["matInput","","formControlName","username"],["type","password","matInput","","formControlName","password"],["matSuffix",""],["formControlName","automaticRecoveryEnabled"],["type","number","step","1","min","0","matInput","","formControlName","connectionTimeout"],["type","number","step","1","min","0","matInput","","formControlName","handshakeTimeout"],["translate","",1,"tb-title"],["required","false","formControlName","clientProperties","keyText","tb.rulenode.key","keyRequiredText","tb.rulenode.key-required","valText","tb.rulenode.value","valRequiredText","tb.rulenode.value-required"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.exchange-name-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-form-field",1)(6,"mat-label",2),t.ɵɵtext(7,"tb.rulenode.routing-key-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(8,"input",4),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"mat-form-field",1)(10,"mat-label",2),t.ɵɵtext(11,"tb.rulenode.message-properties"),t.ɵɵelementEnd(),t.ɵɵelementStart(12,"mat-select",5),t.ɵɵtemplate(13,el,2,2,"mat-option",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(14,"div",7)(15,"mat-form-field",8)(16,"mat-label",2),t.ɵɵtext(17,"tb.rulenode.host"),t.ɵɵelementEnd(),t.ɵɵelement(18,"input",9),t.ɵɵtemplate(19,tl,3,3,"mat-error",10),t.ɵɵelementEnd(),t.ɵɵelementStart(20,"mat-form-field",11)(21,"mat-label",2),t.ɵɵtext(22,"tb.rulenode.port"),t.ɵɵelementEnd(),t.ɵɵelement(23,"input",12),t.ɵɵtemplate(24,nl,3,3,"mat-error",10)(25,rl,3,3,"mat-error",10)(26,al,3,3,"mat-error",10),t.ɵɵelementEnd()(),t.ɵɵelementStart(27,"mat-form-field",1)(28,"mat-label",2),t.ɵɵtext(29,"tb.rulenode.virtual-host"),t.ɵɵelementEnd(),t.ɵɵelement(30,"input",13),t.ɵɵelementEnd(),t.ɵɵelementStart(31,"mat-form-field",1)(32,"mat-label",2),t.ɵɵtext(33,"tb.rulenode.username"),t.ɵɵelementEnd(),t.ɵɵelement(34,"input",14),t.ɵɵelementEnd(),t.ɵɵelementStart(35,"mat-form-field",1)(36,"mat-label",2),t.ɵɵtext(37,"tb.rulenode.password"),t.ɵɵelementEnd(),t.ɵɵelement(38,"input",15)(39,"tb-toggle-password",16),t.ɵɵelementEnd(),t.ɵɵelementStart(40,"mat-checkbox",17),t.ɵɵtext(41),t.ɵɵpipe(42,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(43,"mat-form-field",1)(44,"mat-label",2),t.ɵɵtext(45,"tb.rulenode.connection-timeout-ms"),t.ɵɵelementEnd(),t.ɵɵelement(46,"input",18),t.ɵɵtemplate(47,il,3,3,"mat-error",10),t.ɵɵelementEnd(),t.ɵɵelementStart(48,"mat-form-field",1)(49,"mat-label",2),t.ɵɵtext(50,"tb.rulenode.handshake-timeout-ms"),t.ɵɵelementEnd(),t.ɵɵelement(51,"input",19),t.ɵɵtemplate(52,ol,3,3,"mat-error",10),t.ɵɵelementEnd(),t.ɵɵelementStart(53,"label",20),t.ɵɵtext(54,"tb.rulenode.client-properties"),t.ɵɵelementEnd(),t.ɵɵelement(55,"tb-kv-map-config-old",21),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.rabbitMqConfigForm),t.ɵɵadvance(13),t.ɵɵproperty("ngForOf",n.messageProperties),t.ɵɵadvance(6),t.ɵɵproperty("ngIf",n.rabbitMqConfigForm.get("host").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.rabbitMqConfigForm.get("port").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.rabbitMqConfigForm.get("port").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.rabbitMqConfigForm.get("port").hasError("max")),t.ɵɵadvance(15),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(42,9,"tb.rulenode.automatic-recovery")," "),t.ɵɵadvance(6),t.ɵɵproperty("ngIf",n.rabbitMqConfigForm.get("connectionTimeout").hasError("min")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.rabbitMqConfigForm.get("handshakeTimeout").hasError("min")))},dependencies:t.ɵɵgetComponentDepsFactory(ll),encapsulation:2})}}e("RabbitMqConfigComponent",ll);const sl=e=>({max:e});function pl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.endpoint-url-pattern-required")," "))}function ml(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",20),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e," ")}}function dl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-checkbox",21),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.use-simple-client-http-factory")," "))}function ul(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",20),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e," ")}}function cl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.proxy-host-required")," "))}function fl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.proxy-port-required")," "))}function gl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.proxy-port-range")," "))}function hl(e,n){if(1&e&&(t.ɵɵelementStart(0,"div")(1,"div",23)(2,"mat-form-field",24)(3,"mat-label",2),t.ɵɵtext(4,"tb.rulenode.proxy-scheme"),t.ɵɵelementEnd(),t.ɵɵelementStart(5,"mat-select",25),t.ɵɵtemplate(6,ul,2,2,"mat-option",7),t.ɵɵelementEnd()(),t.ɵɵelementStart(7,"mat-form-field",26)(8,"mat-label",2),t.ɵɵtext(9,"tb.rulenode.proxy-host"),t.ɵɵelementEnd(),t.ɵɵelement(10,"input",27),t.ɵɵtemplate(11,cl,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(12,"mat-form-field",28)(13,"mat-label",2),t.ɵɵtext(14,"tb.rulenode.proxy-port"),t.ɵɵelementEnd(),t.ɵɵelement(15,"input",29),t.ɵɵtemplate(16,fl,3,3,"mat-error",4)(17,gl,3,3,"mat-error",4),t.ɵɵelementEnd()(),t.ɵɵelementStart(18,"mat-form-field",5)(19,"mat-label",2),t.ɵɵtext(20,"tb.rulenode.proxy-user"),t.ɵɵelementEnd(),t.ɵɵelement(21,"input",30),t.ɵɵelementEnd(),t.ɵɵelementStart(22,"mat-form-field",5)(23,"mat-label",2),t.ɵɵtext(24,"tb.rulenode.proxy-password"),t.ɵɵelementEnd(),t.ɵɵelement(25,"input",31),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(6),t.ɵɵproperty("ngForOf",e.proxySchemes),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",e.restApiCallConfigForm.get("proxyHost").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",e.restApiCallConfigForm.get("proxyPort").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.restApiCallConfigForm.get("proxyPort").hasError("min")||e.restApiCallConfigForm.get("proxyPort").hasError("max"))}}function yl(e,n){if(1&e&&(t.ɵɵelementStart(0,"div")(1,"mat-checkbox",22),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(4,hl,26,4,"div",4),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(3,2,"tb.rulenode.use-system-proxy-properties")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!e.restApiCallConfigForm.get("useSystemProxyProperties").value)}}function bl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.int-range")," "))}function vl(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",1)(1,"mat-label",2),t.ɵɵtext(2,"tb.rulenode.read-timeout"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",32),t.ɵɵelementStart(4,"mat-hint",2),t.ɵɵtext(5,"tb.rulenode.read-timeout-hint"),t.ɵɵelementEnd(),t.ɵɵtemplate(6,bl,3,3,"mat-error",4),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(3),t.ɵɵproperty("max",e.IntLimit),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.restApiCallConfigForm.get("readTimeoutMs").hasError("max"))}}function xl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.int-range")," "))}function Cl(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind2(2,1,"tb.rulenode.memory-buffer-size-range",t.ɵɵpureFunction1(4,sl,e.MemoryBufferSizeInKbLimit))," ")}}class Sl extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.proxySchemes=["http","https"],this.httpRequestTypes=Object.keys(Dt),this.MemoryBufferSizeInKbLimit=25e3,this.IntLimit=tn}configForm(){return this.restApiCallConfigForm}onConfigurationSet(e){this.restApiCallConfigForm=this.fb.group({restEndpointUrlPattern:[e?e.restEndpointUrlPattern:null,[N.required]],requestMethod:[e?e.requestMethod:null,[N.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,[N.min(0),N.max(tn)]],maxParallelRequestsCount:[e?e.maxParallelRequestsCount:null,[N.min(0),N.max(tn)]],headers:[e?e.headers:null,[]],credentials:[e?e.credentials:null,[]],maxInMemoryBufferSizeInKb:[e?e.maxInMemoryBufferSizeInKb:null,[N.min(1),N.max(this.MemoryBufferSizeInKbLimit)]]})}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?[N.required]:[]),this.restApiCallConfigForm.get("proxyPort").setValidators(n?[N.required,N.min(1),N.max(65535)]:[])):(this.restApiCallConfigForm.get("proxyHost").setValidators([]),this.restApiCallConfigForm.get("proxyPort").setValidators([]),t?this.restApiCallConfigForm.get("readTimeoutMs").setValidators([]):this.restApiCallConfigForm.get("readTimeoutMs").setValidators([N.min(0),N.max(tn)])),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})}static{this.ɵfac=function(e){return new(e||Sl)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Sl,selectors:[["tb-external-node-rest-api-call-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:48,vars:26,consts:[[1,"flex","flex-col",3,"formGroup"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","restEndpointUrlPattern"],[4,"ngIf"],[1,"mat-block"],["formControlName","requestMethod"],[3,"value",4,"ngFor","ngForOf"],["formControlName","enableProxy"],["formControlName","useSimpleClientHttpFactory",4,"ngIf"],["formControlName","parseToPlainText"],["translate","",1,"tb-hint",2,"padding-bottom","5px"],["formControlName","ignoreRequestBody"],["class","mat-block","subscriptSizing","dynamic",4,"ngIf"],["type","text","min","0","inputmode","numeric","pattern","[0-9]*","matInput","","formControlName","maxParallelRequestsCount",3,"max"],["type","text","min","1","inputmode","numeric","pattern","[0-9]*","matInput","","formControlName","maxInMemoryBufferSizeInKb",3,"max"],["translate","",1,"tb-title"],[1,"tb-hint",3,"innerHTML"],["required","false","formControlName","headers","keyText","tb.rulenode.header","keyRequiredText","tb.rulenode.header-required","valText","tb.rulenode.value","valRequiredText","tb.rulenode.value-required"],["formControlName","credentials",3,"disableCertPemCredentials"],[3,"value"],["formControlName","useSimpleClientHttpFactory"],["formControlName","useSystemProxyProperties"],[1,"gt-sm:flex","gt-sm:flex-row","gt-sm:gap-2"],[1,"mat-block","gt-sm:max-w-10%","gt-sm:flex-full"],["formControlName","proxyScheme"],[1,"md-block","gt-sm:max-w-50%","gt-sm:flex-full"],["matInput","","required","","formControlName","proxyHost"],[1,"mat-block","gt-sm:max-w-40%","gt-sm:flex-full"],["matInput","","required","","formControlName","proxyPort","type","number","step","1"],["matInput","","formControlName","proxyUser"],["matInput","","formControlName","proxyPassword"],["type","text","min","0","inputmode","numeric","pattern","[0-9]*","matInput","","formControlName","readTimeoutMs",3,"max"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.endpoint-url-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,pl,3,3,"mat-error",4),t.ɵɵelementStart(6,"mat-hint",2),t.ɵɵtext(7,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(8,"mat-form-field",5)(9,"mat-label",2),t.ɵɵtext(10,"tb.rulenode.request-method"),t.ɵɵelementEnd(),t.ɵɵelementStart(11,"mat-select",6),t.ɵɵtemplate(12,ml,2,2,"mat-option",7),t.ɵɵelementEnd()(),t.ɵɵelementStart(13,"mat-checkbox",8),t.ɵɵtext(14),t.ɵɵpipe(15,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(16,dl,3,3,"mat-checkbox",9),t.ɵɵelementStart(17,"mat-checkbox",10),t.ɵɵtext(18),t.ɵɵpipe(19,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(20,"div",11),t.ɵɵtext(21,"tb.rulenode.parse-to-plain-text-hint"),t.ɵɵelementEnd(),t.ɵɵelementStart(22,"mat-checkbox",12),t.ɵɵtext(23),t.ɵɵpipe(24,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(25,yl,5,4,"div",4)(26,vl,7,2,"mat-form-field",13),t.ɵɵelementStart(27,"mat-form-field",1)(28,"mat-label",2),t.ɵɵtext(29,"tb.rulenode.max-parallel-requests-count"),t.ɵɵelementEnd(),t.ɵɵelement(30,"input",14),t.ɵɵelementStart(31,"mat-hint",2),t.ɵɵtext(32,"tb.rulenode.max-parallel-requests-count-hint"),t.ɵɵelementEnd(),t.ɵɵtemplate(33,xl,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(34,"mat-form-field",1)(35,"mat-label",2),t.ɵɵtext(36,"tb.rulenode.max-response-size"),t.ɵɵelementEnd(),t.ɵɵelement(37,"input",15),t.ɵɵelementStart(38,"mat-hint",2),t.ɵɵtext(39,"tb.rulenode.max-response-size-hint"),t.ɵɵelementEnd(),t.ɵɵtemplate(40,Cl,3,6,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(41,"label",16),t.ɵɵtext(42,"tb.rulenode.headers"),t.ɵɵelementEnd(),t.ɵɵelement(43,"div",17),t.ɵɵpipe(44,"translate"),t.ɵɵpipe(45,"safe"),t.ɵɵelement(46,"tb-kv-map-config-old",18)(47,"tb-credentials-config",19),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.restApiCallConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.restApiCallConfigForm.get("restEndpointUrlPattern").hasError("required")),t.ɵɵadvance(7),t.ɵɵproperty("ngForOf",n.httpRequestTypes),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(15,15,"tb.rulenode.enable-proxy")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!n.restApiCallConfigForm.get("enableProxy").value),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(19,17,"tb.rulenode.parse-to-plain-text")," "),t.ɵɵadvance(5),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(24,19,"tb.rulenode.ignore-request-body")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.restApiCallConfigForm.get("enableProxy").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",!n.restApiCallConfigForm.get("useSimpleClientHttpFactory").value||n.restApiCallConfigForm.get("enableProxy").value),t.ɵɵadvance(4),t.ɵɵproperty("max",n.IntLimit),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.restApiCallConfigForm.get("maxParallelRequestsCount").hasError("max")),t.ɵɵadvance(4),t.ɵɵproperty("max",n.MemoryBufferSizeInKbLimit),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.restApiCallConfigForm.get("maxInMemoryBufferSizeInKb").hasError("min")||n.restApiCallConfigForm.get("maxInMemoryBufferSizeInKb").hasError("max")),t.ɵɵadvance(3),t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(45,23,t.ɵɵpipeBind1(44,21,"tb.rulenode.headers-hint"),"html"),t.ɵɵsanitizeHtml),t.ɵɵadvance(4),t.ɵɵproperty("disableCertPemCredentials",n.restApiCallConfigForm.get("useSimpleClientHttpFactory").value))},dependencies:t.ɵɵgetComponentDepsFactory(Sl),encapsulation:2})}}function Tl(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",22),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.toUpperCase()," ")}}function Il(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.smtp-host-required")," "))}function El(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.smtp-port-required")," "))}function Fl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.smtp-port-range")," "))}function ql(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.smtp-port-range")," "))}function Al(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.timeout-required")," "))}function kl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-timeout-msec-message")," "))}function Nl(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",22),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e," ")}}function wl(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",4)(1,"mat-label",5),t.ɵɵtext(2,"tb.rulenode.tls-version"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"mat-select",23),t.ɵɵtemplate(4,Nl,2,2,"mat-option",7),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(4),t.ɵɵproperty("ngForOf",e.tlsVersions)}}function Ml(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.proxy-host-required")," "))}function Bl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.proxy-port-required")," "))}function Vl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.proxy-port-range")," "))}function Ol(e,n){if(1&e&&(t.ɵɵelementStart(0,"div")(1,"div",8)(2,"mat-form-field",9)(3,"mat-label",5),t.ɵɵtext(4,"tb.rulenode.proxy-host"),t.ɵɵelementEnd(),t.ɵɵelement(5,"input",24),t.ɵɵtemplate(6,Ml,3,3,"mat-error",11),t.ɵɵelementEnd(),t.ɵɵelementStart(7,"mat-form-field",12)(8,"mat-label",5),t.ɵɵtext(9,"tb.rulenode.proxy-port"),t.ɵɵelementEnd(),t.ɵɵelement(10,"input",25),t.ɵɵtemplate(11,Bl,3,3,"mat-error",11)(12,Vl,3,3,"mat-error",11),t.ɵɵelementEnd()(),t.ɵɵelementStart(13,"mat-form-field",4)(14,"mat-label",5),t.ɵɵtext(15,"tb.rulenode.proxy-user"),t.ɵɵelementEnd(),t.ɵɵelement(16,"input",26),t.ɵɵelementEnd(),t.ɵɵelementStart(17,"mat-form-field",4)(18,"mat-label",5),t.ɵɵtext(19,"tb.rulenode.proxy-password"),t.ɵɵelementEnd(),t.ɵɵelement(20,"input",27),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext(2);t.ɵɵadvance(6),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("proxyHost").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("proxyPort").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("proxyPort").hasError("min")||e.sendEmailConfigForm.get("proxyPort").hasError("max"))}}function Dl(e,n){if(1&e&&(t.ɵɵelementStart(0,"section",3)(1,"mat-form-field",4)(2,"mat-label",5),t.ɵɵtext(3,"tb.rulenode.smtp-protocol"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"mat-select",6),t.ɵɵtemplate(5,Tl,2,2,"mat-option",7),t.ɵɵelementEnd()(),t.ɵɵelementStart(6,"div",8)(7,"mat-form-field",9)(8,"mat-label",5),t.ɵɵtext(9,"tb.rulenode.smtp-host"),t.ɵɵelementEnd(),t.ɵɵelement(10,"input",10),t.ɵɵtemplate(11,Il,3,3,"mat-error",11),t.ɵɵelementEnd(),t.ɵɵelementStart(12,"mat-form-field",12)(13,"mat-label",5),t.ɵɵtext(14,"tb.rulenode.smtp-port"),t.ɵɵelementEnd(),t.ɵɵelement(15,"input",13),t.ɵɵtemplate(16,El,3,3,"mat-error",11)(17,Fl,3,3,"mat-error",11)(18,ql,3,3,"mat-error",11),t.ɵɵelementEnd()(),t.ɵɵelementStart(19,"mat-form-field",4)(20,"mat-label",5),t.ɵɵtext(21,"tb.rulenode.timeout-msec"),t.ɵɵelementEnd(),t.ɵɵelement(22,"input",14),t.ɵɵtemplate(23,Al,3,3,"mat-error",11)(24,kl,3,3,"mat-error",11),t.ɵɵelementEnd(),t.ɵɵelementStart(25,"mat-checkbox",15),t.ɵɵtext(26),t.ɵɵpipe(27,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(28,wl,5,1,"mat-form-field",16),t.ɵɵelementStart(29,"tb-checkbox",17),t.ɵɵtext(30),t.ɵɵpipe(31,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(32,Ol,21,3,"div",11),t.ɵɵelementStart(33,"mat-form-field",18)(34,"mat-label",5),t.ɵɵtext(35,"tb.rulenode.username"),t.ɵɵelementEnd(),t.ɵɵelement(36,"input",19),t.ɵɵpipe(37,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(38,"mat-form-field",18)(39,"mat-label",5),t.ɵɵtext(40,"tb.rulenode.password"),t.ɵɵelementEnd(),t.ɵɵelement(41,"input",20),t.ɵɵpipe(42,"translate"),t.ɵɵelement(43,"tb-toggle-password",21),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(5),t.ɵɵproperty("ngForOf",e.smtpProtocols),t.ɵɵadvance(6),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("smtpHost").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("smtpPort").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("smtpPort").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("smtpPort").hasError("max")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("timeout").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("timeout").hasError("min")),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(27,13,"tb.rulenode.enable-tls")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!0===e.sendEmailConfigForm.get("enableTls").value),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(31,15,"tb.rulenode.enable-proxy")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",e.sendEmailConfigForm.get("enableProxy").value),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("placeholder",t.ɵɵpipeBind1(37,17,"tb.rulenode.enter-username")),t.ɵɵadvance(5),t.ɵɵpropertyInterpolate("placeholder",t.ɵɵpipeBind1(42,19,"tb.rulenode.enter-password"))}}e("RestApiCallConfigComponent",Sl);class Ll extends i{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([N.required]),this.sendEmailConfigForm.get("smtpHost").setValidators([N.required]),this.sendEmailConfigForm.get("smtpPort").setValidators([N.required,N.min(1),N.max(65535)]),this.sendEmailConfigForm.get("timeout").setValidators([N.required,N.min(0)]),this.sendEmailConfigForm.get("proxyHost").setValidators(n?[N.required]:[]),this.sendEmailConfigForm.get("proxyPort").setValidators(n?[N.required,N.min(1),N.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})}static{this.ɵfac=function(e){return new(e||Ll)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Ll,selectors:[["tb-external-node-send-email-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:5,vars:5,consts:[[1,"flex","flex-col",3,"formGroup"],["formControlName","useSystemSmtpSettings"],["class","flex flex-col",4,"ngIf"],[1,"flex","flex-col"],[1,"mat-block"],["translate",""],["formControlName","smtpProtocol"],[3,"value",4,"ngFor","ngForOf"],[1,"gt-sm:flex","gt-sm:flex-row","gt-sm:gap-2"],[1,"mat-block","gt-sm:max-w-60%","gt-sm:flex-full"],["required","","matInput","","formControlName","smtpHost"],[4,"ngIf"],[1,"mat-block","gt-sm:max-w-40%","gt-sm:flex-full"],["required","","type","number","step","1","min","1","max","65535","matInput","","formControlName","smtpPort"],["required","","type","number","step","1","min","0","matInput","","formControlName","timeout"],["formControlName","enableTls"],["class","mat-block",4,"ngIf"],["formControlName","enableProxy"],["floatLabel","always",1,"mat-block"],["matInput","","formControlName","username",3,"placeholder"],["matInput","","type","password","formControlName","password",3,"placeholder"],["matSuffix",""],[3,"value"],["formControlName","tlsVersion"],["matInput","","required","","formControlName","proxyHost"],["matInput","","required","","formControlName","proxyPort","type","number","step","1","min","1","max","65535"],["matInput","","formControlName","proxyUser"],["matInput","","formControlName","proxyPassword"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-checkbox",1),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(4,Dl,44,21,"section",2),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.sendEmailConfigForm),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(3,3,"tb.rulenode.use-system-smtp-settings")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!1===n.sendEmailConfigForm.get("useSystemSmtpSettings").value))},dependencies:t.ɵɵgetComponentDepsFactory(Ll),encapsulation:2})}}function Pl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.numbers-to-template-required")," "))}function Rl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.sms-message-template-required")," "))}function _l(e,n){1&e&&t.ɵɵelement(0,"tb-sms-provider-configuration",9)}e("SendEmailConfigComponent",Ll);class jl extends i{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,[N.required]],smsMessageTemplate:[e?e.smsMessageTemplate:null,[N.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([N.required]),this.sendSmsConfigForm.get("smsProviderConfiguration").updateValueAndValidity({emitEvent:e})}static{this.ɵfac=function(e){return new(e||jl)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:jl,selectors:[["tb-external-node-send-sms-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:20,vars:13,consts:[[1,"flex","flex-col",3,"formGroup"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","numbersToTemplate"],[4,"ngIf"],[3,"innerHTML"],["required","","matInput","","formControlName","smsMessageTemplate","rows","6"],["formControlName","useSystemSmsSettings"],["formControlName","smsProviderConfiguration","required","",4,"ngIf"],["formControlName","smsProviderConfiguration","required",""]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.numbers-to-template"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,Pl,3,3,"mat-error",4),t.ɵɵelement(6,"mat-hint",5),t.ɵɵpipe(7,"translate"),t.ɵɵpipe(8,"safe"),t.ɵɵelementEnd(),t.ɵɵelementStart(9,"mat-form-field",1)(10,"mat-label",2),t.ɵɵtext(11,"tb.rulenode.sms-message-template"),t.ɵɵelementEnd(),t.ɵɵelement(12,"textarea",6),t.ɵɵtemplate(13,Rl,3,3,"mat-error",4),t.ɵɵelementStart(14,"mat-hint",2),t.ɵɵtext(15,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(16,"mat-checkbox",7),t.ɵɵtext(17),t.ɵɵpipe(18,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(19,_l,1,0,"tb-sms-provider-configuration",8),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.sendSmsConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.sendSmsConfigForm.get("numbersToTemplate").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(8,8,t.ɵɵpipeBind1(7,6,"tb.rulenode.numbers-to-template-hint"),"html"),t.ɵɵsanitizeHtml),t.ɵɵadvance(7),t.ɵɵproperty("ngIf",n.sendSmsConfigForm.get("smsMessageTemplate").hasError("required")),t.ɵɵadvance(4),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(18,11,"tb.rulenode.use-system-sms-settings")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!1===n.sendSmsConfigForm.get("useSystemSmsSettings").value))},dependencies:t.ɵɵgetComponentDepsFactory(jl),encapsulation:2})}}function Gl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.message-template-required")," "))}function Kl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.slack-api-token-required")," "))}function Ul(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",11)(1,"mat-label",2),t.ɵɵtext(2,"tb.rulenode.slack-api-token"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",12),t.ɵɵtemplate(4,Kl,3,3,"mat-error",4),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵproperty("ngIf",e.slackConfigForm.get("botToken").hasError("required"))}}function Hl(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-radio-button",13),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.slackChanelTypesTranslateMap.get(e))," ")}}e("SendSmsConfigComponent",jl);class zl extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.slackChanelTypes=Object.keys(F),this.slackChanelTypesTranslateMap=q}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,[N.required]],conversationType:[e?e.conversationType:null,[N.required]],conversation:[e?e.conversation:null,[N.required]]})}validatorTriggers(){return["useSystemSettings"]}updateValidators(e){this.slackConfigForm.get("useSystemSettings").value?this.slackConfigForm.get("botToken").clearValidators():this.slackConfigForm.get("botToken").setValidators([N.required]),this.slackConfigForm.get("botToken").updateValueAndValidity({emitEvent:e})}static{this.ɵfac=function(e){return new(e||zl)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:zl,selectors:[["tb-external-node-slack-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:18,vars:12,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"mat-block","flex-1"],["translate",""],["required","","matInput","","formControlName","messageTemplate"],[4,"ngIf"],["formControlName","useSystemSettings"],["class","mat-block",4,"ngIf"],[1,"tb-title"],["formControlName","conversationType"],[3,"value",4,"ngFor","ngForOf"],["formControlName","conversation","required","",3,"token","slackChanelType"],[1,"mat-block"],["required","","matInput","","formControlName","botToken"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.message-template"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,Gl,3,3,"mat-error",4),t.ɵɵelementStart(6,"mat-hint",2),t.ɵɵtext(7,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(8,"mat-checkbox",5),t.ɵɵtext(9),t.ɵɵpipe(10,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(11,Ul,5,1,"mat-form-field",6),t.ɵɵelementStart(12,"label",7),t.ɵɵtext(13),t.ɵɵpipe(14,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(15,"mat-radio-group",8),t.ɵɵtemplate(16,Hl,3,4,"mat-radio-button",9),t.ɵɵelementEnd(),t.ɵɵelement(17,"tb-slack-conversation-autocomplete",10),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.slackConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.slackConfigForm.get("messageTemplate").hasError("required")),t.ɵɵadvance(4),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(10,8,"tb.rulenode.use-system-slack-settings")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",!n.slackConfigForm.get("useSystemSettings").value),t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(14,10,"notification.slack-chanel-type")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.slackChanelTypes),t.ɵɵadvance(),t.ɵɵproperty("token",n.slackConfigForm.get("useSystemSettings").value?"":n.slackConfigForm.get("botToken").value)("slackChanelType",n.slackConfigForm.get("conversationType").value))},dependencies:t.ɵɵgetComponentDepsFactory(zl),styles:["[_nghost-%COMP%] .tb-title[_ngcontent-%COMP%]{display:block;padding-bottom:6px}[_nghost-%COMP%] .mat-mdc-radio-group{display:flex;flex-direction:row;margin-bottom:22px;gap:12px}[_nghost-%COMP%] .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){[_nghost-%COMP%] .mat-mdc-radio-group{flex-direction:column}}"]})}}function $l(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.topic-arn-pattern-required")," "))}function Ql(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.aws-access-key-id-required")," "))}function Jl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.aws-secret-access-key-required")," "))}function Yl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.aws-region-required")," "))}e("SlackConfigComponent",zl);class Wl extends i{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,[N.required]],accessKeyId:[e?e.accessKeyId:null,[N.required]],secretAccessKey:[e?e.secretAccessKey:null,[N.required]],region:[e?e.region:null,[N.required]]})}static{this.ɵfac=function(e){return new(e||Wl)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Wl,selectors:[["tb-external-node-sns-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:23,vars:5,consts:[[1,"flex","flex-col",3,"formGroup"],["subscriptSizing","dynamic",1,"mat-block"],["translate",""],["required","","matInput","","formControlName","topicArnPattern"],[4,"ngIf"],[1,"mat-block"],["required","","matInput","","formControlName","accessKeyId"],["required","","matInput","","formControlName","secretAccessKey"],["required","","matInput","","formControlName","region"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.topic-arn-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",3),t.ɵɵtemplate(5,$l,3,3,"mat-error",4),t.ɵɵelementStart(6,"mat-hint",2),t.ɵɵtext(7,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵelementStart(8,"mat-form-field",5)(9,"mat-label",2),t.ɵɵtext(10,"tb.rulenode.aws-access-key-id"),t.ɵɵelementEnd(),t.ɵɵelement(11,"input",6),t.ɵɵtemplate(12,Ql,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(13,"mat-form-field",5)(14,"mat-label",2),t.ɵɵtext(15,"tb.rulenode.aws-secret-access-key"),t.ɵɵelementEnd(),t.ɵɵelement(16,"input",7),t.ɵɵtemplate(17,Jl,3,3,"mat-error",4),t.ɵɵelementEnd(),t.ɵɵelementStart(18,"mat-form-field",5)(19,"mat-label",2),t.ɵɵtext(20,"tb.rulenode.aws-region"),t.ɵɵelementEnd(),t.ɵɵelement(21,"input",8),t.ɵɵtemplate(22,Yl,3,3,"mat-error",4),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.snsConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.snsConfigForm.get("topicArnPattern").hasError("required")),t.ɵɵadvance(7),t.ɵɵproperty("ngIf",n.snsConfigForm.get("accessKeyId").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.snsConfigForm.get("secretAccessKey").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.snsConfigForm.get("region").hasError("required")))},dependencies:t.ɵɵgetComponentDepsFactory(Wl),encapsulation:2})}}function Xl(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",15),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.sqsQueueTypeTranslationsMap.get(e))," ")}}function Zl(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.queue-url-pattern-required")," "))}function es(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.min-delay-seconds-message")," "))}function ts(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-delay-seconds-message")," "))}function ns(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",1)(1,"mat-label",2),t.ɵɵtext(2,"tb.rulenode.delay-seconds"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",16),t.ɵɵtemplate(4,es,3,3,"mat-error",7)(5,ts,3,3,"mat-error",7),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵproperty("ngIf",e.sqsConfigForm.get("delaySeconds").hasError("min")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.sqsConfigForm.get("delaySeconds").hasError("max"))}}function rs(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.aws-access-key-id-required")," "))}function as(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.aws-secret-access-key-required")," "))}function is(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.aws-region-required")," "))}e("SnsConfigComponent",Wl);class os extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.sqsQueueType=Nt,this.sqsQueueTypes=Object.keys(Nt),this.sqsQueueTypeTranslationsMap=wt}configForm(){return this.sqsConfigForm}onConfigurationSet(e){this.sqsConfigForm=this.fb.group({queueType:[e?e.queueType:null,[N.required]],queueUrlPattern:[e?e.queueUrlPattern:null,[N.required]],delaySeconds:[e?e.delaySeconds:null,[N.min(0),N.max(900)]],messageAttributes:[e?e.messageAttributes:null,[]],accessKeyId:[e?e.accessKeyId:null,[N.required]],secretAccessKey:[e?e.secretAccessKey:null,[N.required]],region:[e?e.region:null,[N.required]]})}static{this.ɵfac=function(e){return new(e||os)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:os,selectors:[["tb-external-node-sqs-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:35,vars:13,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"mat-block"],["translate",""],["formControlName","queueType","required",""],[3,"value",4,"ngFor","ngForOf"],["subscriptSizing","dynamic",1,"mat-block"],["required","","matInput","","formControlName","queueUrlPattern"],[4,"ngIf"],["class","mat-block",4,"ngIf"],["translate","",1,"tb-title"],[1,"tb-hint",3,"innerHTML"],["required","false","formControlName","messageAttributes","keyText","tb.rulenode.name","keyRequiredText","tb.rulenode.name-required","valText","tb.rulenode.value","valRequiredText","tb.rulenode.value-required"],["required","","matInput","","formControlName","accessKeyId"],["required","","matInput","","formControlName","secretAccessKey"],["required","","matInput","","formControlName","region"],[3,"value"],["required","","type","number","min","0","max","900","step","1","matInput","","formControlName","delaySeconds"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.queue-type"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"mat-select",3),t.ɵɵtemplate(5,Xl,3,4,"mat-option",4),t.ɵɵelementEnd()(),t.ɵɵelementStart(6,"mat-form-field",5)(7,"mat-label",2),t.ɵɵtext(8,"tb.rulenode.queue-url-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(9,"input",6),t.ɵɵtemplate(10,Zl,3,3,"mat-error",7),t.ɵɵelementStart(11,"mat-hint",2),t.ɵɵtext(12,"tb.rulenode.general-pattern-hint"),t.ɵɵelementEnd()(),t.ɵɵtemplate(13,ns,6,2,"mat-form-field",8),t.ɵɵelementStart(14,"label",9),t.ɵɵtext(15,"tb.rulenode.message-attributes"),t.ɵɵelementEnd(),t.ɵɵelement(16,"div",10),t.ɵɵpipe(17,"translate"),t.ɵɵpipe(18,"safe"),t.ɵɵelement(19,"tb-kv-map-config-old",11),t.ɵɵelementStart(20,"mat-form-field",1)(21,"mat-label",2),t.ɵɵtext(22,"tb.rulenode.aws-access-key-id"),t.ɵɵelementEnd(),t.ɵɵelement(23,"input",12),t.ɵɵtemplate(24,rs,3,3,"mat-error",7),t.ɵɵelementEnd(),t.ɵɵelementStart(25,"mat-form-field",1)(26,"mat-label",2),t.ɵɵtext(27,"tb.rulenode.aws-secret-access-key"),t.ɵɵelementEnd(),t.ɵɵelement(28,"input",13),t.ɵɵtemplate(29,as,3,3,"mat-error",7),t.ɵɵelementEnd(),t.ɵɵelementStart(30,"mat-form-field",1)(31,"mat-label",2),t.ɵɵtext(32,"tb.rulenode.aws-region"),t.ɵɵelementEnd(),t.ɵɵelement(33,"input",14),t.ɵɵtemplate(34,is,3,3,"mat-error",7),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.sqsConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("ngForOf",n.sqsQueueTypes),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.sqsConfigForm.get("queueUrlPattern").hasError("required")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.sqsConfigForm.get("queueType").value===n.sqsQueueType.STANDARD),t.ɵɵadvance(3),t.ɵɵproperty("innerHTML",t.ɵɵpipeBind2(18,10,t.ɵɵpipeBind1(17,8,"tb.rulenode.message-attributes-hint"),"html"),t.ɵɵsanitizeHtml),t.ɵɵadvance(8),t.ɵɵproperty("ngIf",n.sqsConfigForm.get("accessKeyId").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.sqsConfigForm.get("secretAccessKey").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.sqsConfigForm.get("region").hasError("required")))},dependencies:t.ɵɵgetComponentDepsFactory(os),encapsulation:2})}}function ls(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.function-name-required")," "))}function ss(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.aws-access-key-id-required")," "))}function ps(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.aws-secret-access-key-required")," "))}function ms(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.aws-region-required")," "))}function ds(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.connection-timeout-required")," "))}function us(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.connection-timeout-min")," "))}function cs(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.request-timeout-required")," "))}function fs(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.request-timeout-min")," "))}e("SqsConfigComponent",os);class gs extends i{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,[N.required]],qualifier:[e?e.qualifier:null,[]],accessKey:[e?e.accessKey:null,[N.required]],secretKey:[e?e.secretKey:null,[N.required]],region:[e?e.region:null,[N.required]],connectionTimeout:[e?e.connectionTimeout:null,[N.required,N.min(0)]],requestTimeout:[e?e.requestTimeout:null,[N.required,N.min(0)]],tellFailureIfFuncThrowsExc:[!!e&&e.tellFailureIfFuncThrowsExc,[]]})}static{this.ɵfac=function(e){return new(e||gs)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:gs,selectors:[["tb-external-node-lambda-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:71,vars:28,consts:[[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],[1,"tb-form-panel","stroked"],[1,"tb-form-row","no-padding","no-border"],["translate","",1,"tb-form-panel-title","tb-required"],["popupHelpLink","rulenode/node-templatization-doc",3,"hintText"],[1,"tb-standard-fields"],[1,"mat-block"],["required","","matInput","","formControlName","functionName"],[4,"ngIf"],["matInput","","formControlName","qualifier"],["translate",""],["expanded","",1,"tb-settings"],["required","","matInput","","formControlName","accessKey"],["required","","matInput","","formControlName","secretKey"],["required","","matInput","","formControlName","region"],[1,"tb-form-panel","stroked","no-padding"],[1,"tb-settings"],[2,"padding","16px"],[1,"tb-form-panel","no-border","no-padding","no-gap",2,"margin-top","0"],[1,"tb-form-row","no-border","same-padding","tb-standard-fields"],[1,"flex"],["type","number","required","","min","0","matInput","","formControlName","connectionTimeout"],["matSuffix","","aria-hidden","false","aria-label","help-icon","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],["type","number","required","","min","0","matInput","","formControlName","requestTimeout"],[1,"tb-form-row","no-border",2,"margin-bottom","16px",3,"tb-hint-tooltip-icon"],["formControlName","tellFailureIfFuncThrowsExc",1,"mat-slide"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2)(3,"div",3),t.ɵɵtext(4,"tb.rulenode.function-configuration"),t.ɵɵelementEnd()(),t.ɵɵelement(5,"tb-example-hint",4),t.ɵɵelementStart(6,"div",5)(7,"mat-form-field",6)(8,"mat-label"),t.ɵɵtext(9),t.ɵɵpipe(10,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(11,"input",7),t.ɵɵtemplate(12,ls,3,3,"mat-error",8),t.ɵɵelementEnd(),t.ɵɵelementStart(13,"mat-form-field",6)(14,"mat-label"),t.ɵɵtext(15),t.ɵɵpipe(16,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(17,"input",9),t.ɵɵelementStart(18,"mat-hint",10),t.ɵɵtext(19,"tb.rulenode.qualifier-hint"),t.ɵɵelementEnd()()()(),t.ɵɵelementStart(20,"div",1)(21,"mat-expansion-panel",11)(22,"mat-expansion-panel-header")(23,"mat-panel-title",3),t.ɵɵtext(24,"tb.rulenode.aws-credentials"),t.ɵɵelementEnd()(),t.ɵɵelementStart(25,"div",5)(26,"mat-form-field",6)(27,"mat-label",10),t.ɵɵtext(28,"tb.rulenode.aws-access-key-id"),t.ɵɵelementEnd(),t.ɵɵelement(29,"input",12),t.ɵɵtemplate(30,ss,3,3,"mat-error",8),t.ɵɵelementEnd(),t.ɵɵelementStart(31,"mat-form-field",6)(32,"mat-label",10),t.ɵɵtext(33,"tb.rulenode.aws-secret-access-key"),t.ɵɵelementEnd(),t.ɵɵelement(34,"input",13),t.ɵɵtemplate(35,ps,3,3,"mat-error",8),t.ɵɵelementEnd(),t.ɵɵelementStart(36,"mat-form-field",6)(37,"mat-label",10),t.ɵɵtext(38,"tb.rulenode.aws-region"),t.ɵɵelementEnd(),t.ɵɵelement(39,"input",14),t.ɵɵtemplate(40,ms,3,3,"mat-error",8),t.ɵɵelementEnd()()()(),t.ɵɵelementStart(41,"div",15)(42,"mat-expansion-panel",16)(43,"mat-expansion-panel-header",17)(44,"mat-panel-title",10),t.ɵɵtext(45,"tb.rulenode.advanced-settings"),t.ɵɵelementEnd()(),t.ɵɵelementStart(46,"div",18)(47,"div",19)(48,"mat-form-field",20)(49,"mat-label",10),t.ɵɵtext(50,"tb.rulenode.connection-timeout"),t.ɵɵelementEnd(),t.ɵɵelement(51,"input",21),t.ɵɵtemplate(52,ds,3,3,"mat-error",8)(53,us,3,3,"mat-error",8),t.ɵɵelementStart(54,"mat-icon",22),t.ɵɵpipe(55,"translate"),t.ɵɵtext(56,"help"),t.ɵɵelementEnd()(),t.ɵɵelementStart(57,"mat-form-field",20)(58,"mat-label",10),t.ɵɵtext(59,"tb.rulenode.request-timeout"),t.ɵɵelementEnd(),t.ɵɵelement(60,"input",23),t.ɵɵtemplate(61,cs,3,3,"mat-error",8)(62,fs,3,3,"mat-error",8),t.ɵɵelementStart(63,"mat-icon",22),t.ɵɵpipe(64,"translate"),t.ɵɵtext(65,"help"),t.ɵɵelementEnd()()(),t.ɵɵelementStart(66,"div",24),t.ɵɵpipe(67,"translate"),t.ɵɵelementStart(68,"mat-slide-toggle",25),t.ɵɵtext(69),t.ɵɵpipe(70,"translate"),t.ɵɵelementEnd()()()()()()),2&e&&(t.ɵɵproperty("formGroup",n.lambdaConfigForm),t.ɵɵadvance(5),t.ɵɵproperty("hintText","tb.rulenode.template-rules-hint"),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(10,16,"tb.rulenode.function-name")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.lambdaConfigForm.get("functionName").hasError("required")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(16,18,"tb.rulenode.qualifier")),t.ɵɵadvance(15),t.ɵɵproperty("ngIf",n.lambdaConfigForm.get("accessKey").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.lambdaConfigForm.get("secretKey").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.lambdaConfigForm.get("region").hasError("required")),t.ɵɵadvance(12),t.ɵɵproperty("ngIf",n.lambdaConfigForm.get("connectionTimeout").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.lambdaConfigForm.get("connectionTimeout").hasError("min")),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(55,20,"tb.rulenode.connection-timeout-hint")),t.ɵɵadvance(7),t.ɵɵproperty("ngIf",n.lambdaConfigForm.get("requestTimeout").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.lambdaConfigForm.get("requestTimeout").hasError("min")),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(64,22,"tb.rulenode.request-timeout-hint")),t.ɵɵadvance(3),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(67,24,"tb.rulenode.tell-failure-aws-lambda-hint")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(70,26,"tb.rulenode.tell-failure-aws-lambda")," "))},dependencies:t.ɵɵgetComponentDepsFactory(gs),encapsulation:2})}}e("LambdaConfigComponent",gs);class hs{static{this.ɵfac=function(e){return new(e||hs)}}static{this.ɵmod=t.ɵɵdefineNgModule({type:hs})}static{this.ɵinj=t.ɵɵdefineInjector({imports:[$,S,Q,xi,Wl,os,gs,Zo,_o,Jo,Yo,ll,Sl,Ll,Ao,jl,zl]})}}e("RulenodeCoreConfigExternalModule",hs),("undefined"==typeof ngJitMode||ngJitMode)&&t.ɵɵsetNgModuleScope(hs,{declarations:[Wl,os,gs,Zo,_o,Jo,Yo,ll,Sl,Ll,Ao,jl,zl],imports:[$,S,Q,xi],exports:[Wl,os,gs,Zo,_o,Jo,Yo,ll,Sl,Ll,Ao,jl,zl]});class ys extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.searchText=""}configForm(){return this.alarmStatusConfigForm}prepareInputConfig(e){return{alarmStatusList:P(e?.alarmStatusList)?e.alarmStatusList:null}}onConfigurationSet(e){this.alarmStatusConfigForm=this.fb.group({alarmStatusList:[e.alarmStatusList,[N.required]]})}static{this.ɵfac=function(e){return new(e||ys)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:ys,selectors:[["tb-filter-node-check-alarm-status-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:7,vars:2,consts:[[1,"tb-form-panel","stroked",3,"formGroup"],[1,"tb-form-row","no-padding","no-border","space-between"],["translate","",1,"tb-form-panel-title","tb-required"],["translate","",1,"tb-form-panel-hint","tb-error",3,"hidden"],["formControlName","alarmStatusList"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2),t.ɵɵtext(3,"tb.rulenode.alarm-status"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"div",3),t.ɵɵtext(5," tb.rulenode.alarm-required "),t.ɵɵelementEnd()(),t.ɵɵelement(6,"tb-alarm-status-select",4),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.alarmStatusConfigForm),t.ɵɵadvance(4),t.ɵɵproperty("hidden",n.alarmStatusConfigForm.get("alarmStatusList").valid))},dependencies:t.ɵɵgetComponentDepsFactory(ys),encapsulation:2})}}e("CheckAlarmStatusComponent",ys);const bs=e=>({inputName:e});class vs extends i{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.checkMessageConfigForm}prepareInputConfig(e){return{messageNames:P(e?.messageNames)?e.messageNames:[],metadataNames:P(e?.metadataNames)?e.metadataNames:[],checkAllKeys:!!P(e?.checkAllKeys)&&e.checkAllKeys}}prepareOutputConfig(e){return{messageNames:P(e?.messageNames)?e.messageNames:[],metadataNames:P(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(N.required,["messageNames","metadataNames"])})}get touchedValidationControl(){return["messageNames","metadataNames"].some((e=>this.checkMessageConfigForm.get(e).touched))}static{this.ɵfac=function(e){return new(e||vs)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:vs,selectors:[["tb-filter-node-check-message-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:25,vars:36,consts:[[1,"tb-form-panel","stroked",3,"formGroup"],[1,"tb-form-row","no-padding","no-border","space-between"],["translate","",1,"tb-form-panel-title","tb-required"],["translate","",1,"tb-form-panel-hint","tb-error",3,"hidden"],["editable","","subscriptSizing","dynamic","formControlName","messageNames",3,"label","placeholder"],["matSuffix","","color","primary","aria-hidden","false","aria-label","help-icon",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],["editable","","subscriptSizing","dynamic","formControlName","metadataNames",3,"label","placeholder"],[1,"tb-form-row","no-border","no-padding",3,"tb-hint-tooltip-icon"],["formControlName","checkAllKeys",1,"mat-slide"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2),t.ɵɵtext(3,"tb.rulenode.fields-to-check"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"div",3),t.ɵɵtext(5," tb.rulenode.at-least-one-field-required "),t.ɵɵelementEnd()(),t.ɵɵelementStart(6,"tb-string-items-list",4),t.ɵɵpipe(7,"translate"),t.ɵɵpipe(8,"translate"),t.ɵɵelementStart(9,"mat-icon",5),t.ɵɵpipe(10,"translate"),t.ɵɵpipe(11,"translate"),t.ɵɵtext(12,"help"),t.ɵɵelementEnd()(),t.ɵɵelementStart(13,"tb-string-items-list",6),t.ɵɵpipe(14,"translate"),t.ɵɵpipe(15,"translate"),t.ɵɵelementStart(16,"mat-icon",5),t.ɵɵpipe(17,"translate"),t.ɵɵpipe(18,"translate"),t.ɵɵtext(19,"help"),t.ɵɵelementEnd()(),t.ɵɵelementStart(20,"div",7),t.ɵɵpipe(21,"translate"),t.ɵɵelementStart(22,"mat-slide-toggle",8),t.ɵɵtext(23),t.ɵɵpipe(24,"translate"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.checkMessageConfigForm),t.ɵɵadvance(4),t.ɵɵproperty("hidden",!(n.touchedValidationControl&&n.checkMessageConfigForm.hasError("atLeastOne"))),t.ɵɵadvance(2),t.ɵɵproperty("label",t.ɵɵpipeBind1(7,10,"tb.rulenode.data-keys"))("placeholder",t.ɵɵpipeBind1(8,12,"tb.rulenode.add-message-field")),t.ɵɵadvance(3),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind2(11,16,"tb.rulenode.chip-help",t.ɵɵpureFunction1(32,bs,t.ɵɵpipeBind1(10,14,"tb.rulenode.field-name")))),t.ɵɵadvance(4),t.ɵɵproperty("label",t.ɵɵpipeBind1(14,19,"tb.rulenode.metadata-keys"))("placeholder",t.ɵɵpipeBind1(15,21,"tb.rulenode.add-metadata-field")),t.ɵɵadvance(3),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind2(18,25,"tb.rulenode.chip-help",t.ɵɵpureFunction1(34,bs,t.ɵɵpipeBind1(17,23,"tb.rulenode.field-name")))),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(21,28,"tb.rulenode.check-all-keys-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(24,30,"tb.rulenode.check-all-keys")," "))},dependencies:t.ɵɵgetComponentDepsFactory(vs),encapsulation:2})}}function xs(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",10),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementStart(3,"span",11),t.ɵɵtext(4,"tb.rulenode.relations-query-config-direction-suffix"),t.ɵɵelementEnd()()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.entitySearchDirectionTranslationsMap.get(e))," ")}}function Cs(e,n){if(1&e&&t.ɵɵelement(0,"tb-entity-autocomplete",15),2&e){const e=t.ɵɵnextContext(2);t.ɵɵproperty("entityType",e.checkRelationConfigForm.get("entityType").value)}}function Ss(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",12),t.ɵɵelement(1,"tb-entity-type-select",13),t.ɵɵtemplate(2,Cs,1,1,"tb-entity-autocomplete",14),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵproperty("ngIf",e.checkRelationConfigForm.get("entityType").value)}}e("CheckMessageConfigComponent",vs);class Ts extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.entitySearchDirection=Object.values(d),this.entitySearchDirectionTranslationsMap=b}configForm(){return this.checkRelationConfigForm}prepareInputConfig(e){return{checkForSingleEntity:!!P(e?.checkForSingleEntity)&&e.checkForSingleEntity,direction:P(e?.direction)?e.direction:null,entityType:P(e?.entityType)?e.entityType:null,entityId:P(e?.entityId)?e.entityId:null,relationType:P(e?.relationType)?e.relationType:null}}onConfigurationSet(e){this.checkRelationConfigForm=this.fb.group({checkForSingleEntity:[e.checkForSingleEntity,[]],direction:[e.direction,[]],entityType:[e.entityType,e&&e.checkForSingleEntity?[N.required]:[]],entityId:[e.entityId,e&&e.checkForSingleEntity?[N.required]:[]],relationType:[e.relationType,[N.required]]})}validatorTriggers(){return["checkForSingleEntity"]}updateValidators(e){const t=this.checkRelationConfigForm.get("checkForSingleEntity").value;this.checkRelationConfigForm.get("entityType").setValidators(t?[N.required]:[]),this.checkRelationConfigForm.get("entityType").updateValueAndValidity({emitEvent:e}),this.checkRelationConfigForm.get("entityId").setValidators(t?[N.required]:[]),this.checkRelationConfigForm.get("entityId").updateValueAndValidity({emitEvent:e})}static{this.ɵfac=function(e){return new(e||Ts)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Ts,selectors:[["tb-filter-node-check-relation-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:17,vars:12,consts:[[1,"tb-form-panel","stroked","no-padding-bottom",3,"formGroup"],["translate","",1,"tb-form-panel-title"],[1,"flex","flex-col"],["hideRequiredMarker","",1,"mat-block"],["formControlName","direction","required",""],[3,"value",4,"ngFor","ngForOf"],["required","","formControlName","relationType"],[1,"tb-form-row","no-border","no-padding","slide-toggle",3,"tb-hint-tooltip-icon"],["formControlName","checkForSingleEntity",1,"mat-slide"],["class","same-width-component-row",4,"ngIf"],[3,"value"],["translate",""],[1,"same-width-component-row"],["showLabel","","required","","formControlName","entityType",2,"min-width","100px","flex","1"],["class","flex-1","required","","formControlName","entityId",3,"entityType",4,"ngIf"],["required","","formControlName","entityId",1,"flex-1",3,"entityType"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵtext(2,"tb.rulenode.relation-search-parameters"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"div",2)(4,"mat-form-field",3)(5,"mat-label"),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-select",4),t.ɵɵtemplate(9,xs,5,4,"mat-option",5),t.ɵɵelementEnd()(),t.ɵɵelement(10,"tb-relation-type-autocomplete",6),t.ɵɵelementStart(11,"div",7),t.ɵɵpipe(12,"translate"),t.ɵɵelementStart(13,"mat-slide-toggle",8),t.ɵɵtext(14),t.ɵɵpipe(15,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(16,Ss,3,1,"div",9),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.checkRelationConfigForm),t.ɵɵadvance(6),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(7,6,"relation.direction")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.entitySearchDirection),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(12,8,"tb.rulenode.check-relation-to-specific-entity-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(15,10,"tb.rulenode.check-relation-to-specific-entity")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.checkRelationConfigForm.get("checkForSingleEntity").value))},dependencies:t.ɵɵgetComponentDepsFactory(Ts),styles:["[_nghost-%COMP%] .slide-toggle[_ngcontent-%COMP%]{margin-bottom:18px}"]})}}e("CheckRelationConfigComponent",Ts);const Is=e=>({perimeterKeyName:e});function Es(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.latitude-field-name-required")," "))}function Fs(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.longitude-field-name-required")," "))}function qs(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",18),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.perimeterTypeTranslationMap.get(e))," ")}}function As(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.perimeter-key-name-required")," "))}function ks(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",19)(1,"mat-label"),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",20),t.ɵɵtemplate(5,As,3,3,"mat-error",6),t.ɵɵelementStart(6,"mat-hint"),t.ɵɵtext(7),t.ɵɵpipe(8,"translate"),t.ɵɵelementEnd()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(3,3,"tb.rulenode.perimeter-key-name")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.geoFilterConfigForm.get("perimeterKeyName").hasError("required")),t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(8,5,"tb.rulenode.perimeter-key-name-hint"))}}function Ns(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.circle-center-latitude-required")," "))}function ws(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.circle-center-longitude-required")," "))}function Ms(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.range-required")," "))}function Bs(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",18),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext(2);t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.rangeUnitTranslationMap.get(e))," ")}}function Vs(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.range-units-required")," "))}function Os(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",9)(1,"div",3)(2,"mat-form-field",21)(3,"mat-label"),t.ɵɵtext(4),t.ɵɵpipe(5,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(6,"input",22),t.ɵɵtemplate(7,Ns,3,3,"mat-error",6),t.ɵɵelementEnd(),t.ɵɵelementStart(8,"mat-form-field",21)(9,"mat-label"),t.ɵɵtext(10),t.ɵɵpipe(11,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(12,"input",23),t.ɵɵtemplate(13,ws,3,3,"mat-error",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(14,"div",3)(15,"mat-form-field",21)(16,"mat-label"),t.ɵɵtext(17),t.ɵɵpipe(18,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(19,"input",24),t.ɵɵtemplate(20,Ms,3,3,"mat-error",6),t.ɵɵelementEnd(),t.ɵɵelementStart(21,"mat-form-field",21)(22,"mat-label"),t.ɵɵtext(23),t.ɵɵpipe(24,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(25,"mat-select",25),t.ɵɵtemplate(26,Bs,3,4,"mat-option",12),t.ɵɵelementEnd(),t.ɵɵtemplate(27,Vs,3,3,"mat-error",6),t.ɵɵelementEnd()()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(5,9,"tb.rulenode.circle-center-latitude")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.geoFilterConfigForm.get("centerLatitude").hasError("required")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(11,11,"tb.rulenode.circle-center-longitude")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.geoFilterConfigForm.get("centerLongitude").hasError("required")),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(18,13,"tb.rulenode.range")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",e.geoFilterConfigForm.get("range").hasError("required")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(24,15,"tb.rulenode.range-units")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",e.rangeUnits),t.ɵɵadvance(),t.ɵɵproperty("ngIf",e.geoFilterConfigForm.get("rangeUnit").hasError("required"))}}function Ds(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.polygon-definition-required")," "))}function Ls(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-form-field",26)(1,"mat-label"),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(4,"input",27),t.ɵɵelementStart(5,"mat-hint"),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(8,Ds,3,3,"mat-error",6),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(2),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(3,3,"tb.rulenode.polygon-definition")),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(7,5,"tb.rulenode.polygon-definition-hint")),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",e.geoFilterConfigForm.get("polygonsDefinition").hasError("required"))}}class Ps extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.perimeterType=ft,this.perimeterTypes=Object.values(ft),this.perimeterTypeTranslationMap=gt,this.rangeUnits=Object.values(bt),this.rangeUnitTranslationMap=vt,this.defaultPaddingEnable=!0}configForm(){return this.geoFilterConfigForm}prepareInputConfig(e){return{latitudeKeyName:P(e?.latitudeKeyName)?e.latitudeKeyName:null,longitudeKeyName:P(e?.longitudeKeyName)?e.longitudeKeyName:null,perimeterType:P(e?.perimeterType)?e.perimeterType:null,fetchPerimeterInfoFromMessageMetadata:!!P(e?.fetchPerimeterInfoFromMessageMetadata)&&e.fetchPerimeterInfoFromMessageMetadata,perimeterKeyName:P(e?.perimeterKeyName)?e.perimeterKeyName:null,centerLatitude:P(e?.centerLatitude)?e.centerLatitude:null,centerLongitude:P(e?.centerLongitude)?e.centerLongitude:null,range:P(e?.range)?e.range:null,rangeUnit:P(e?.rangeUnit)?e.rangeUnit:null,polygonsDefinition:P(e?.polygonsDefinition)?e.polygonsDefinition:null}}onConfigurationSet(e){this.geoFilterConfigForm=this.fb.group({latitudeKeyName:[e.latitudeKeyName,[N.required]],longitudeKeyName:[e.longitudeKeyName,[N.required]],perimeterType:[e.perimeterType,[N.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([N.required]):this.geoFilterConfigForm.get("perimeterKeyName").setValidators([]),t||n!==ft.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([N.required,N.min(-90),N.max(90)]),this.geoFilterConfigForm.get("centerLongitude").setValidators([N.required,N.min(-180),N.max(180)]),this.geoFilterConfigForm.get("range").setValidators([N.required,N.min(0)]),this.geoFilterConfigForm.get("rangeUnit").setValidators([N.required]),this.defaultPaddingEnable=!1),t||n!==ft.POLYGON?this.geoFilterConfigForm.get("polygonsDefinition").setValidators([]):this.geoFilterConfigForm.get("polygonsDefinition").setValidators([N.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})}static{this.ɵfac=function(e){return new(e||Ps)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Ps,selectors:[["tb-filter-node-gps-geofencing-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:39,vars:32,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],[1,"tb-form-panel","stroked"],["translate","",1,"tb-form-panel-title"],[1,"flex","flex-row","gap-4"],[1,"mat-block","max-w-50%","flex-full"],["matInput","","formControlName","latitudeKeyName","required",""],[4,"ngIf"],["matInput","","formControlName","longitudeKeyName","required",""],["translate","",1,"tb-form-hint","tb-primary-fill"],[1,"flex","flex-col"],["hideRequiredMarker","",1,"mat-block","flex-1"],["formControlName","perimeterType"],[3,"value",4,"ngFor","ngForOf"],[1,"tb-form-row","no-border","no-padding","slide-toggle",3,"tb-hint-tooltip-icon"],["formControlName","fetchPerimeterInfoFromMessageMetadata",1,"mat-slide"],["class","mat-block",4,"ngIf"],["class","flex flex-col",4,"ngIf"],["class","mat-block","subscriptSizing","dynamic",4,"ngIf"],[3,"value"],[1,"mat-block"],["matInput","","formControlName","perimeterKeyName","required",""],[1,"flex-1"],["type","number","min","-90","max","90","step","0.1","matInput","","formControlName","centerLatitude","required",""],["type","number","min","-180","max","180","step","0.1","matInput","","formControlName","centerLongitude","required",""],["type","number","min","0","step","0.1","matInput","","formControlName","range","required",""],["formControlName","rangeUnit","required",""],["subscriptSizing","dynamic",1,"mat-block"],["matInput","","formControlName","polygonsDefinition","required",""]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"section",1)(2,"div",2),t.ɵɵtext(3,"tb.rulenode.coordinate-field-names"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"section")(5,"div",3)(6,"mat-form-field",4)(7,"mat-label"),t.ɵɵtext(8),t.ɵɵpipe(9,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(10,"input",5),t.ɵɵtemplate(11,Es,3,3,"mat-error",6),t.ɵɵelementEnd(),t.ɵɵelementStart(12,"mat-form-field",4)(13,"mat-label"),t.ɵɵtext(14),t.ɵɵpipe(15,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(16,"input",7),t.ɵɵtemplate(17,Fs,3,3,"mat-error",6),t.ɵɵelementEnd()(),t.ɵɵelementStart(18,"div",8),t.ɵɵtext(19,"tb.rulenode.coordinate-field-hint"),t.ɵɵelementEnd()()(),t.ɵɵelementStart(20,"section",1)(21,"div",2),t.ɵɵtext(22,"tb.rulenode.geofence-configuration"),t.ɵɵelementEnd(),t.ɵɵelementStart(23,"section",9)(24,"mat-form-field",10)(25,"mat-label"),t.ɵɵtext(26),t.ɵɵpipe(27,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(28,"mat-select",11),t.ɵɵtemplate(29,qs,3,4,"mat-option",12),t.ɵɵelementEnd()(),t.ɵɵelementStart(30,"div",13),t.ɵɵpipe(31,"translate"),t.ɵɵpipe(32,"translate"),t.ɵɵelementStart(33,"mat-slide-toggle",14),t.ɵɵtext(34),t.ɵɵpipe(35,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(36,ks,9,7,"mat-form-field",15)(37,Os,28,17,"div",16)(38,Ls,9,7,"mat-form-field",17),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.geoFilterConfigForm),t.ɵɵadvance(8),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(9,14,"tb.rulenode.latitude-field-name")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.geoFilterConfigForm.get("latitudeKeyName").hasError("required")),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(15,16,"tb.rulenode.longitude-field-name")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.geoFilterConfigForm.get("longitudeKeyName").hasError("required")),t.ɵɵadvance(3),t.ɵɵclassProp("no-padding-bottom",!n.defaultPaddingEnable),t.ɵɵadvance(6),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(27,18,"tb.rulenode.perimeter-type")),t.ɵɵadvance(3),t.ɵɵproperty("ngForOf",n.perimeterTypes),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",n.geoFilterConfigForm.get("perimeterType").value===n.perimeterType.CIRCLE?t.ɵɵpipeBind2(31,20,"tb.rulenode.fetch-circle-parameter-info-from-metadata-hint",t.ɵɵpureFunction1(28,Is,n.geoFilterConfigForm.get("perimeterKeyName").valid?n.geoFilterConfigForm.get("perimeterKeyName").value:"ss_perimeter")):t.ɵɵpipeBind2(32,23,"tb.rulenode.fetch-poligon-parameter-info-from-metadata-hint",t.ɵɵpureFunction1(30,Is,n.geoFilterConfigForm.get("perimeterKeyName").valid?n.geoFilterConfigForm.get("perimeterKeyName").value:"ss_perimeter"))),t.ɵɵadvance(4),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(35,26,"tb.rulenode.fetch-perimeter-info-from-metadata")," "),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.geoFilterConfigForm.get("perimeterType").value===n.perimeterType.CIRCLE&&!n.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.geoFilterConfigForm.get("perimeterType").value===n.perimeterType.POLYGON&&!n.geoFilterConfigForm.get("fetchPerimeterInfoFromMessageMetadata").value))},dependencies:t.ɵɵgetComponentDepsFactory(Ps),styles:["[_nghost-%COMP%] .slide-toggle[_ngcontent-%COMP%]{margin-bottom:18px}"]})}}e("GpsGeoFilterConfigComponent",Ps);class Rs extends i{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.messageTypeConfigForm}prepareInputConfig(e){return{messageTypes:P(e?.messageTypes)?e.messageTypes:null}}onConfigurationSet(e){this.messageTypeConfigForm=this.fb.group({messageTypes:[e.messageTypes,[N.required]]})}static{this.ɵfac=function(e){return new(e||Rs)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Rs,selectors:[["tb-filter-node-message-type-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:3,vars:4,consts:[[3,"formGroup"],["required","","formControlName","messageTypes",3,"label"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0),t.ɵɵelement(1,"tb-message-types-config",1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.messageTypeConfigForm),t.ɵɵadvance(),t.ɵɵproperty("label",t.ɵɵpipeBind1(2,2,"tb.rulenode.select-message-types")))},dependencies:t.ɵɵgetComponentDepsFactory(Rs),encapsulation:2})}}e("MessageTypeConfigComponent",Rs);const _s=e=>({inputName:e});class js extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.allowedEntityTypes=[u.DEVICE,u.ASSET,u.ENTITY_VIEW,u.TENANT,u.CUSTOMER,u.USER,u.DASHBOARD,u.RULE_CHAIN,u.RULE_NODE,u.EDGE]}configForm(){return this.originatorTypeConfigForm}prepareInputConfig(e){return{originatorTypes:P(e?.originatorTypes)?e.originatorTypes:null}}onConfigurationSet(e){this.originatorTypeConfigForm=this.fb.group({originatorTypes:[e.originatorTypes,[N.required]]})}static{this.ɵfac=function(e){return new(e||js)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:js,selectors:[["tb-filter-node-originator-type-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:9,vars:20,consts:[[3,"formGroup"],["formControlName","originatorTypes","required","",1,"flex-1",3,"allowedEntityTypes","ignoreAuthorityFilter","emptyInputPlaceholder","filledInputPlaceholder","label"],["matSuffix","","aria-hidden","false","aria-label","help-icon","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"tb-entity-type-list",1),t.ɵɵpipe(2,"translate"),t.ɵɵpipe(3,"translate"),t.ɵɵpipe(4,"translate"),t.ɵɵelementStart(5,"mat-icon",2),t.ɵɵpipe(6,"translate"),t.ɵɵpipe(7,"translate"),t.ɵɵtext(8,"help"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.originatorTypeConfigForm),t.ɵɵadvance(),t.ɵɵproperty("allowedEntityTypes",n.allowedEntityTypes)("ignoreAuthorityFilter",!0)("emptyInputPlaceholder",t.ɵɵpipeBind1(2,7,"tb.rulenode.add-entity-type"))("filledInputPlaceholder",t.ɵɵpipeBind1(3,9,"tb.rulenode.add-entity-type"))("label",t.ɵɵpipeBind1(4,11,"tb.rulenode.select-entity-types")),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind2(7,15,"tb.rulenode.chip-help",t.ɵɵpureFunction1(18,_s,t.ɵɵpipeBind1(6,13,"tb.rulenode.entity-type")))))},dependencies:t.ɵɵgetComponentDepsFactory(js),encapsulation:2})}}e("OriginatorTypeConfigComponent",js);const Gs=["jsFuncComponent"],Ks=["tbelFuncComponent"],Us=()=>["msg","metadata","msgType"];function Hs(e,n){1&e&&t.ɵɵelement(0,"tb-script-lang",7)}function zs(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",8,0)(2,"button",9),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",10),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(4,Us)),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,2,e.testScriptLabel))}}function $s(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",11,1)(2,"button",9),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",10),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(6,Us))("disableUndefinedCheck",!0)("scriptLanguage",e.scriptLanguage.TBEL),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,4,e.testScriptLabel))}}class Qs extends i{constructor(e,t,r,a){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=r,this.translate=a,this.tbelEnabled=D(this.store).tbelEnabled,this.scriptLanguage=s,this.changeScript=new n,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-filter-function"}configForm(){return this.scriptConfigForm}onConfigurationSet(e){this.scriptConfigForm=this.fb.group({scriptLang:[e.scriptLang,[N.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==s.TBEL||this.tbelEnabled||(t=s.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===s.JS?[N.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===s.TBEL?[N.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=s.JS)),{scriptLang:P(e?.scriptLang)?e.scriptLang:s.JS,jsScript:P(e?.jsScript)?e.jsScript:null,tbelScript:P(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===s.JS?"jsScript":"tbelScript",r=t===s.JS?"rulenode/filter_node_script_fn":"rulenode/tbel/filter_node_script_fn",a=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(a,"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===s.JS&&this.jsFuncComponent.validateOnSubmit()}static{this.ɵfac=function(e){return new(e||Qs)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder),t.ɵɵdirectiveInject(L.NodeScriptTestService),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Qs,selectors:[["tb-filter-node-script-config"]],viewQuery:function(e,n){if(1&e&&(t.ɵɵviewQuery(Gs,5),t.ɵɵviewQuery(Ks,5)),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.jsFuncComponent=e.first),t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.tbelFuncComponent=e.first)}},features:[t.ɵɵInheritDefinitionFeature],decls:7,vars:7,consts:[["jsFuncComponent",""],["tbelFuncComponent",""],[3,"formGroup"],["formControlName","scriptLang",4,"ngIf"],["formControlName","jsScript","functionName","Filter","helpId","rulenode/filter_node_script_fn","noValidate","true",3,"functionArgs",4,"ngIf"],["formControlName","tbelScript","functionName","Filter","helpId","rulenode/tbel/filter_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage",4,"ngIf"],["mat-button","","mat-raised-button","","color","primary",3,"click"],["formControlName","scriptLang"],["formControlName","jsScript","functionName","Filter","helpId","rulenode/filter_node_script_fn","noValidate","true",3,"functionArgs"],["toolbarSuffixButton","","mat-icon-button","","matTooltipPosition","above",1,"tb-mat-32",3,"click","matTooltip"],["color","primary",1,"material-icons"],["formControlName","tbelScript","functionName","Filter","helpId","rulenode/tbel/filter_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",2),t.ɵɵtemplate(1,Hs,1,0,"tb-script-lang",3)(2,zs,6,5,"tb-js-func",4)(3,$s,6,7,"tb-js-func",5),t.ɵɵelementStart(4,"button",6),t.ɵɵlistener("click",(function(){return n.testScript()})),t.ɵɵtext(5),t.ɵɵpipe(6,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.scriptConfigForm),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.tbelEnabled),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.scriptConfigForm.get("scriptLang").value===n.scriptLanguage.JS),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.scriptConfigForm.get("scriptLang").value===n.scriptLanguage.TBEL),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(6,5,n.testScriptLabel)," "))},dependencies:t.ɵɵgetComponentDepsFactory(Qs),encapsulation:2})}}e("ScriptConfigComponent",Qs);const Js=["jsFuncComponent"],Ys=["tbelFuncComponent"],Ws=()=>["msg","metadata","msgType"];function Xs(e,n){1&e&&t.ɵɵelement(0,"tb-script-lang",7)}function Zs(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",8,0)(2,"button",9),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",10),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(4,Ws)),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,2,e.testScriptLabel))}}function ep(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",11,1)(2,"button",9),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",10),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(6,Ws))("disableUndefinedCheck",!0)("scriptLanguage",e.scriptLanguage.TBEL),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,4,e.testScriptLabel))}}class tp extends i{constructor(e,t,r,a){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=r,this.translate=a,this.tbelEnabled=D(this.store).tbelEnabled,this.scriptLanguage=s,this.changeScript=new n,this.hasScript=!0,this.testScriptLabel="tb.rulenode.test-switch-function"}configForm(){return this.switchConfigForm}onConfigurationSet(e){this.switchConfigForm=this.fb.group({scriptLang:[e.scriptLang,[N.required]],jsScript:[e.jsScript,[]],tbelScript:[e.tbelScript,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.switchConfigForm.get("scriptLang").value;t!==s.TBEL||this.tbelEnabled||(t=s.JS,this.switchConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.switchConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.switchConfigForm.get("jsScript").setValidators(t===s.JS?[N.required]:[]),this.switchConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.switchConfigForm.get("tbelScript").setValidators(t===s.TBEL?[N.required]:[]),this.switchConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=s.JS)),{scriptLang:P(e?.scriptLang)?e.scriptLang:s.JS,jsScript:P(e?.jsScript)?e.jsScript:null,tbelScript:P(e?.tbelScript)?e.tbelScript:null}}testScript(e){const t=this.switchConfigForm.get("scriptLang").value,n=t===s.JS?"jsScript":"tbelScript",r=t===s.JS?"rulenode/switch_node_script_fn":"rulenode/tbel/switch_node_script_fn",a=this.switchConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(a,"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===s.JS&&this.jsFuncComponent.validateOnSubmit()}static{this.ɵfac=function(e){return new(e||tp)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder),t.ɵɵdirectiveInject(L.NodeScriptTestService),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:tp,selectors:[["tb-filter-node-switch-config"]],viewQuery:function(e,n){if(1&e&&(t.ɵɵviewQuery(Js,5),t.ɵɵviewQuery(Ys,5)),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.jsFuncComponent=e.first),t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.tbelFuncComponent=e.first)}},features:[t.ɵɵInheritDefinitionFeature],decls:7,vars:7,consts:[["jsFuncComponent",""],["tbelFuncComponent",""],[3,"formGroup"],["formControlName","scriptLang",4,"ngIf"],["formControlName","jsScript","functionName","Switch","helpId","rulenode/switch_node_script_fn","noValidate","true",3,"functionArgs",4,"ngIf"],["formControlName","tbelScript","functionName","Switch","helpId","rulenode/tbel/switch_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage",4,"ngIf"],["mat-button","","mat-raised-button","","color","primary",3,"click"],["formControlName","scriptLang"],["formControlName","jsScript","functionName","Switch","helpId","rulenode/switch_node_script_fn","noValidate","true",3,"functionArgs"],["toolbarSuffixButton","","mat-icon-button","","matTooltipPosition","above",1,"tb-mat-32",3,"click","matTooltip"],["color","primary",1,"material-icons"],["formControlName","tbelScript","functionName","Switch","helpId","rulenode/tbel/switch_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",2),t.ɵɵtemplate(1,Xs,1,0,"tb-script-lang",3)(2,Zs,6,5,"tb-js-func",4)(3,ep,6,7,"tb-js-func",5),t.ɵɵelementStart(4,"button",6),t.ɵɵlistener("click",(function(){return n.testScript()})),t.ɵɵtext(5),t.ɵɵpipe(6,"translate"),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.switchConfigForm),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.tbelEnabled),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.switchConfigForm.get("scriptLang").value===n.scriptLanguage.JS),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.switchConfigForm.get("scriptLang").value===n.scriptLanguage.TBEL),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(6,5,n.testScriptLabel)," "))},dependencies:t.ɵɵgetComponentDepsFactory(tp),encapsulation:2})}}e("SwitchConfigComponent",tp);class np{static{this.ɵfac=function(e){return new(e||np)}}static{this.ɵmod=t.ɵɵdefineNgModule({type:np})}static{this.ɵinj=t.ɵɵdefineInjector({imports:[$,S,xi,vs,Ts,Ps,Rs,js,Qs,tp,ys]})}}function rp(e,n){if(1&e&&(t.ɵɵelementStart(0,"span"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,e.originatorSourceTranslationMap.get(e.changeOriginatorConfigForm.get("originatorSource").value))," ")}}function ap(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",8)(1,"span",9),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(4,"br"),t.ɵɵelementStart(5,"small",10),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd()()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(3,3,r.originatorSourceTranslationMap.get(e))," "),t.ɵɵadvance(4),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(7,5,r.originatorSourceDescTranslationMap.get(e))," ")}}function ip(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.entity-name-pattern-required")," "))}function op(e,n){if(1&e&&(t.ɵɵelementStart(0,"div",11),t.ɵɵelement(1,"tb-example-hint",12),t.ɵɵelementStart(2,"div",13),t.ɵɵelement(3,"tb-entity-type-select",14),t.ɵɵelementStart(4,"mat-form-field",15)(5,"mat-label",2),t.ɵɵtext(6,"tb.rulenode.entity-name-pattern"),t.ɵɵelementEnd(),t.ɵɵelement(7,"input",16),t.ɵɵtemplate(8,ip,3,3,"mat-error",4),t.ɵɵelementEnd()()()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵproperty("hintText","tb.rulenode.entity-name-pattern-hint"),t.ɵɵadvance(2),t.ɵɵproperty("allowedEntityTypes",e.allowedEntityTypes),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",e.changeOriginatorConfigForm.get("entityNamePattern").hasError("required")||e.changeOriginatorConfigForm.get("entityNamePattern").hasError("pattern"))}}function lp(e,n){1&e&&t.ɵɵelement(0,"tb-relations-query-config",17)}e("RuleNodeCoreConfigFilterModule",np),("undefined"==typeof ngJitMode||ngJitMode)&&t.ɵɵsetNgModuleScope(np,{declarations:[vs,Ts,Ps,Rs,js,Qs,tp,ys],imports:[$,S,xi],exports:[vs,Ts,Ps,Rs,js,Qs,tp,ys]});class sp extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.originatorSource=pt,this.originatorSources=Object.keys(pt),this.originatorSourceTranslationMap=mt,this.originatorSourceDescTranslationMap=dt,this.allowedEntityTypes=[u.DEVICE,u.ASSET,u.ENTITY_VIEW,u.USER,u.EDGE]}configForm(){return this.changeOriginatorConfigForm}onConfigurationSet(e){this.changeOriginatorConfigForm=this.fb.group({originatorSource:[e?e.originatorSource:null,[N.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===pt.RELATED?this.changeOriginatorConfigForm.get("relationsQuery").setValidators([N.required]):this.changeOriginatorConfigForm.get("relationsQuery").setValidators([]),t===pt.ENTITY?(this.changeOriginatorConfigForm.get("entityType").setValidators([N.required]),this.changeOriginatorConfigForm.get("entityNamePattern").setValidators([N.required,N.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})}static{this.ɵfac=function(e){return new(e||sp)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:sp,selectors:[["tb-transformation-node-change-originator-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:10,vars:5,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],["subscriptSizing","dynamic","hideRequiredMarker","",1,"mat-block"],["translate",""],["formControlName","originatorSource","required",""],[4,"ngIf"],[3,"value",4,"ngFor","ngForOf"],["class","tb-form-panel stroked no-padding-bottom",4,"ngIf"],["required","","formControlName","relationsQuery",4,"ngIf"],[3,"value"],["matListItemTitle",""],["matListItemMeta","",2,"color","inherit"],[1,"tb-form-panel","stroked","no-padding-bottom"],["popupHelpLink","rulenode/change_originator_node_fields_templatization",3,"hintText"],[1,"tb-form-row","no-border","no-padding","tb-standard-fields"],["showLabel","","required","","formControlName","entityType",1,"mat-mdc-form-field","flex",3,"allowedEntityTypes"],[1,"flex"],["required","","matInput","","formControlName","entityNamePattern"],["required","","formControlName","relationsQuery"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label",2),t.ɵɵtext(3,"tb.rulenode.new-originator"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"mat-select",3)(5,"mat-select-trigger"),t.ɵɵtemplate(6,rp,3,3,"span",4),t.ɵɵelementEnd(),t.ɵɵtemplate(7,ap,8,7,"mat-option",5),t.ɵɵelementEnd()(),t.ɵɵtemplate(8,op,9,3,"div",6)(9,lp,1,0,"tb-relations-query-config",7),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.changeOriginatorConfigForm),t.ɵɵadvance(6),t.ɵɵproperty("ngIf",n.originatorSourceTranslationMap.get(n.changeOriginatorConfigForm.get("originatorSource").value)),t.ɵɵadvance(),t.ɵɵproperty("ngForOf",n.originatorSources),t.ɵɵadvance(),t.ɵɵproperty("ngIf","ENTITY"===n.changeOriginatorConfigForm.get("originatorSource").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.changeOriginatorConfigForm.get("originatorSource").value===n.originatorSource.RELATED))},dependencies:t.ɵɵgetComponentDepsFactory(sp),encapsulation:2})}}e("ChangeOriginatorConfigComponent",sp);const pp=["jsFuncComponent"],mp=["tbelFuncComponent"],dp=()=>["msg","metadata","msgType"];function up(e,n){1&e&&t.ɵɵelement(0,"tb-script-lang",7)}function cp(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",8,0)(2,"button",9),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",10),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(4,dp)),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,2,e.testScriptLabel))}}function fp(e,n){if(1&e){const e=t.ɵɵgetCurrentView();t.ɵɵelementStart(0,"tb-js-func",11,1)(2,"button",9),t.ɵɵpipe(3,"translate"),t.ɵɵlistener("click",(function(){t.ɵɵrestoreView(e);const n=t.ɵɵnextContext();return t.ɵɵresetView(n.testScript())})),t.ɵɵelementStart(4,"mat-icon",10),t.ɵɵtext(5,"bug_report"),t.ɵɵelementEnd()()()}if(2&e){const e=t.ɵɵnextContext();t.ɵɵproperty("functionArgs",t.ɵɵpureFunction0(6,dp))("disableUndefinedCheck",!0)("scriptLanguage",e.scriptLanguage.TBEL),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(3,4,e.testScriptLabel))}}class gp extends i{constructor(e,t,r,a){super(e),this.store=e,this.fb=t,this.nodeScriptTestService=r,this.translate=a,this.tbelEnabled=D(this.store).tbelEnabled,this.scriptLanguage=s,this.changeScript=new n,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:s.JS,[N.required]],jsScript:[e?e.jsScript:null,[N.required]],tbelScript:[e?e.tbelScript:null,[]]})}validatorTriggers(){return["scriptLang"]}updateValidators(e){let t=this.scriptConfigForm.get("scriptLang").value;t!==s.TBEL||this.tbelEnabled||(t=s.JS,this.scriptConfigForm.get("scriptLang").patchValue(t,{emitEvent:!1}),setTimeout((()=>{this.scriptConfigForm.updateValueAndValidity({emitEvent:!0})}))),this.scriptConfigForm.get("jsScript").setValidators(t===s.JS?[N.required]:[]),this.scriptConfigForm.get("jsScript").updateValueAndValidity({emitEvent:e}),this.scriptConfigForm.get("tbelScript").setValidators(t===s.TBEL?[N.required]:[]),this.scriptConfigForm.get("tbelScript").updateValueAndValidity({emitEvent:e})}prepareInputConfig(e){return e&&(e.scriptLang||(e.scriptLang=s.JS)),e}testScript(e){const t=this.scriptConfigForm.get("scriptLang").value,n=t===s.JS?"jsScript":"tbelScript",r=t===s.JS?"rulenode/transformation_node_script_fn":"rulenode/tbel/transformation_node_script_fn",a=this.scriptConfigForm.get(n).value;this.nodeScriptTestService.testNodeScript(a,"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===s.JS&&this.jsFuncComponent.validateOnSubmit()}static{this.ɵfac=function(e){return new(e||gp)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder),t.ɵɵdirectiveInject(L.NodeScriptTestService),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:gp,selectors:[["tb-transformation-node-script-config"]],viewQuery:function(e,n){if(1&e&&(t.ɵɵviewQuery(pp,5),t.ɵɵviewQuery(mp,5)),2&e){let e;t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.jsFuncComponent=e.first),t.ɵɵqueryRefresh(e=t.ɵɵloadQuery())&&(n.tbelFuncComponent=e.first)}},features:[t.ɵɵInheritDefinitionFeature],decls:8,vars:7,consts:[["jsFuncComponent",""],["tbelFuncComponent",""],[3,"formGroup"],["formControlName","scriptLang",4,"ngIf"],["formControlName","jsScript","functionName","Transform","helpId","rulenode/transformation_node_script_fn","noValidate","true",3,"functionArgs",4,"ngIf"],["formControlName","tbelScript","functionName","Transform","helpId","rulenode/tbel/transformation_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage",4,"ngIf"],["mat-button","","mat-raised-button","","color","primary",3,"click"],["formControlName","scriptLang"],["formControlName","jsScript","functionName","Transform","helpId","rulenode/transformation_node_script_fn","noValidate","true",3,"functionArgs"],["toolbarSuffixButton","","mat-icon-button","","matTooltipPosition","above",1,"tb-mat-32",3,"click","matTooltip"],["color","primary",1,"material-icons"],["formControlName","tbelScript","functionName","Transform","helpId","rulenode/tbel/transformation_node_script_fn","noValidate","true",3,"functionArgs","disableUndefinedCheck","scriptLanguage"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",2),t.ɵɵtemplate(1,up,1,0,"tb-script-lang",3)(2,cp,6,5,"tb-js-func",4)(3,fp,6,7,"tb-js-func",5),t.ɵɵelementStart(4,"div")(5,"button",6),t.ɵɵlistener("click",(function(){return n.testScript()})),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.scriptConfigForm),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.tbelEnabled),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.scriptConfigForm.get("scriptLang").value===n.scriptLanguage.JS),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.scriptConfigForm.get("scriptLang").value===n.scriptLanguage.TBEL),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(7,5,n.testScriptLabel)," "))},dependencies:t.ɵɵgetComponentDepsFactory(gp),encapsulation:2})}}e("TransformScriptConfigComponent",gp);const hp=()=>({maxWidth:"820px"});function yp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.from-template-required")," "))}function bp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.to-template-required")," "))}function vp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.subject-template-required")," "))}function xp(e,n){if(1&e&&(t.ɵɵelementStart(0,"span"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=t.ɵɵnextContext();t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,e.getBodyTypeName())," ")}}function Cp(e,n){if(1&e&&(t.ɵɵelementStart(0,"mat-option",24)(1,"span",25),t.ɵɵtext(2),t.ɵɵpipe(3,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(4,"br"),t.ɵɵelementStart(5,"small",26),t.ɵɵtext(6),t.ɵɵpipe(7,"translate"),t.ɵɵelementEnd()()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e.value),t.ɵɵadvance(2),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(3,3,e.name)," "),t.ɵɵadvance(4),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(7,5,e.description)," ")}}function Sp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-form-field",18)(1,"mat-label",5),t.ɵɵtext(2,"tb.rulenode.body-type-template"),t.ɵɵelementEnd(),t.ɵɵelement(3,"input",27),t.ɵɵelementStart(4,"mat-hint",5),t.ɵɵtext(5,"tb.mail-body-type.after-template-evaluation-hint"),t.ɵɵelementEnd()())}function Tp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.body-template-required")," "))}class Ip extends i{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,[N.required]],toTemplate:[e?e.toTemplate:null,[N.required]],ccTemplate:[e?e.ccTemplate:null,[]],bccTemplate:[e?e.bccTemplate:null,[]],subjectTemplate:[e?e.subjectTemplate:null,[N.required]],mailBodyType:[e?e.mailBodyType:null],isHtmlTemplate:[e?e.isHtmlTemplate:null,[N.required]],bodyTemplate:[e?e.bodyTemplate:null,[N.required]]})}prepareInputConfig(e){return{fromTemplate:P(e?.fromTemplate)?e.fromTemplate:null,toTemplate:P(e?.toTemplate)?e.toTemplate:null,ccTemplate:P(e?.ccTemplate)?e.ccTemplate:null,bccTemplate:P(e?.bccTemplate)?e.bccTemplate:null,subjectTemplate:P(e?.subjectTemplate)?e.subjectTemplate:null,mailBodyType:P(e?.mailBodyType)?e.mailBodyType:null,isHtmlTemplate:P(e?.isHtmlTemplate)?e.isHtmlTemplate:null,bodyTemplate:P(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}static{this.ɵfac=function(e){return new(e||Ip)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Ip,selectors:[["tb-transformation-node-to-email-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:61,vars:23,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],[1,"tb-form-panel","stroked"],["translate","",1,"tb-form-panel-title"],[1,"tb-form-row","no-border","no-padding","tb-standard-fields"],["subscriptSizing","dynamic",1,"flex"],["translate",""],["required","","matInput","","formControlName","fromTemplate"],["align","start"],["align","end"],[1,"input-bottom-double-hint"],["hintMode","","tb-help-popup-placement","right","trigger-style","letter-spacing:0.25px; font-size:12px;",1,"see-example",3,"tb-help-popup","tb-help-popup-style","trigger-text"],[4,"ngIf"],[1,"tb-form-panel","no-padding","no-border"],["popupHelpLink","rulenode/to_email_node_fields_templatization",3,"hintText"],[1,"flex"],["required","","matInput","","formControlName","toTemplate","cdkTextareaAutosize","","cdkAutosizeMinRows","1",1,"tb-enable-vertical-resize"],["matInput","","formControlName","ccTemplate","cdkTextareaAutosize","","cdkAutosizeMinRows","1",1,"tb-enable-vertical-resize"],["matInput","","formControlName","bccTemplate","cdkTextareaAutosize","","cdkAutosizeMinRows","1",1,"tb-enable-vertical-resize"],[1,"mat-block"],["required","","matInput","","formControlName","subjectTemplate","cdkTextareaAutosize","","cdkAutosizeMinRows","1",1,"tb-enable-vertical-resize"],["formControlName","mailBodyType"],[3,"value",4,"ngFor","ngForOf"],["class","mat-block",4,"ngIf"],["required","","matInput","","formControlName","bodyTemplate","cdkTextareaAutosize","","cdkAutosizeMinRows","2",1,"tb-enable-vertical-resize"],[3,"value"],["matListItemTitle",""],["matListItemMeta","",2,"color","inherit"],["required","","matInput","","formControlName","isHtmlTemplate"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2),t.ɵɵtext(3,"tb.rulenode.email-sender"),t.ɵɵelementEnd(),t.ɵɵelementStart(4,"div",3)(5,"mat-form-field",4)(6,"mat-label",5),t.ɵɵtext(7,"tb.rulenode.from-template"),t.ɵɵelementEnd(),t.ɵɵelement(8,"input",6),t.ɵɵelementStart(9,"mat-hint",7),t.ɵɵtext(10),t.ɵɵpipe(11,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(12,"mat-hint",8)(13,"div",9),t.ɵɵelement(14,"div",10),t.ɵɵpipe(15,"translate"),t.ɵɵelementEnd()(),t.ɵɵtemplate(16,yp,3,3,"mat-error",11),t.ɵɵelementEnd()()(),t.ɵɵelementStart(17,"div",1)(18,"div",12)(19,"div",2),t.ɵɵtext(20,"tb.rulenode.recipients"),t.ɵɵelementEnd(),t.ɵɵelement(21,"tb-example-hint",13),t.ɵɵpipe(22,"translate"),t.ɵɵelementEnd(),t.ɵɵelementStart(23,"div",3)(24,"mat-form-field",14)(25,"mat-label",5),t.ɵɵtext(26,"tb.rulenode.to-template"),t.ɵɵelementEnd(),t.ɵɵelement(27,"textarea",15),t.ɵɵtemplate(28,bp,3,3,"mat-error",11),t.ɵɵelementEnd(),t.ɵɵelementStart(29,"mat-form-field",14)(30,"mat-label",5),t.ɵɵtext(31,"tb.rulenode.cc-template"),t.ɵɵelementEnd(),t.ɵɵelement(32,"textarea",16),t.ɵɵelementEnd(),t.ɵɵelementStart(33,"mat-form-field",14)(34,"mat-label",5),t.ɵɵtext(35,"tb.rulenode.bcc-template"),t.ɵɵelementEnd(),t.ɵɵelement(36,"textarea",17),t.ɵɵelementEnd()()(),t.ɵɵelementStart(37,"div",1)(38,"div",2),t.ɵɵtext(39,"tb.rulenode.message-subject-and-content"),t.ɵɵelementEnd(),t.ɵɵelement(40,"tb-example-hint",13),t.ɵɵpipe(41,"translate"),t.ɵɵelementStart(42,"section")(43,"mat-form-field",18)(44,"mat-label",5),t.ɵɵtext(45,"tb.rulenode.subject-template"),t.ɵɵelementEnd(),t.ɵɵelement(46,"textarea",19),t.ɵɵtemplate(47,vp,3,3,"mat-error",11),t.ɵɵelementEnd(),t.ɵɵelementStart(48,"mat-form-field",18)(49,"mat-label",5),t.ɵɵtext(50,"tb.rulenode.mail-body-type"),t.ɵɵelementEnd(),t.ɵɵelementStart(51,"mat-select",20)(52,"mat-select-trigger"),t.ɵɵtemplate(53,xp,3,3,"span",11),t.ɵɵelementEnd(),t.ɵɵtemplate(54,Cp,8,7,"mat-option",21),t.ɵɵelementEnd()(),t.ɵɵtemplate(55,Sp,6,0,"mat-form-field",22),t.ɵɵelementStart(56,"mat-form-field",18)(57,"mat-label",5),t.ɵɵtext(58,"tb.rulenode.body-template"),t.ɵɵelementEnd(),t.ɵɵelement(59,"textarea",23),t.ɵɵtemplate(60,Tp,3,3,"mat-error",11),t.ɵɵelementEnd()()()()),2&e&&(t.ɵɵproperty("formGroup",n.toEmailConfigForm),t.ɵɵadvance(10),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(11,14,"tb.rulenode.email-from-template-hint")," "),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("tb-help-popup","rulenode/to_email_node_fields_templatization"),t.ɵɵpropertyInterpolate("trigger-text",t.ɵɵpipeBind1(15,16,"tb.key-val.see-examples")),t.ɵɵproperty("tb-help-popup-style",t.ɵɵpureFunction0(22,hp)),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.toEmailConfigForm.get("fromTemplate").hasError("required")),t.ɵɵadvance(5),t.ɵɵproperty("hintText",t.ɵɵpipeBind1(22,18,"tb.rulenode.recipients-block-main-hint")),t.ɵɵadvance(7),t.ɵɵproperty("ngIf",n.toEmailConfigForm.get("toTemplate").hasError("required")),t.ɵɵadvance(12),t.ɵɵproperty("hintText",t.ɵɵpipeBind1(41,20,"tb.rulenode.kv-map-pattern-hint")),t.ɵɵadvance(7),t.ɵɵproperty("ngIf",n.toEmailConfigForm.get("subjectTemplate").hasError("required")),t.ɵɵadvance(6),t.ɵɵproperty("ngIf",n.toEmailConfigForm.get("mailBodyType").value),t.ɵɵadvance(),t.ɵɵproperty("ngForOf",n.mailBodyTypes),t.ɵɵadvance(),t.ɵɵproperty("ngIf","dynamic"===n.toEmailConfigForm.get("mailBodyType").value),t.ɵɵadvance(5),t.ɵɵproperty("ngIf",n.toEmailConfigForm.get("bodyTemplate").hasError("required")))},dependencies:t.ɵɵgetComponentDepsFactory(Ip),styles:["[_nghost-%COMP%] .input-bottom-double-hint[_ngcontent-%COMP%]{display:inline-flex}[_nghost-%COMP%] .input-bottom-double-hint[_ngcontent-%COMP%] .see-example[_ngcontent-%COMP%]{flex-shrink:0;padding-right:16px}[_nghost-%COMP%] textarea.tb-enable-vertical-resize[_ngcontent-%COMP%]{resize:vertical}"]})}}e("ToEmailConfigComponent",Ip);class Ep extends i{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.copyFrom=[],this.translation=Ut;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,[N.required]],keys:[e?e.keys:null,[N.required]]})}configForm(){return this.copyKeysConfigForm}prepareInputConfig(e){let t;return t=P(e?.fromMetadata)?e.copyFrom?Kt.METADATA:Kt.DATA:P(e?.copyFrom)?e.copyFrom:Kt.DATA,{keys:P(e?.keys)?e.keys:null,copyFrom:t}}static{this.ɵfac=function(e){return new(e||Ep)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Ep,selectors:[["tb-transformation-node-copy-keys-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:10,vars:17,consts:[[1,"tb-form-panel","no-padding","no-border",3,"formGroup"],["formControlName","copyFrom",3,"labelText","translation"],["required","","formControlName","keys",1,"mat-block",3,"label","placeholder","requiredText"],["matSuffix","","aria-hidden","false","aria-label","help-icon","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0),t.ɵɵelement(1,"tb-msg-metadata-chip",1),t.ɵɵpipe(2,"translate"),t.ɵɵelementStart(3,"tb-string-items-list",2),t.ɵɵpipe(4,"translate"),t.ɵɵpipe(5,"translate"),t.ɵɵpipe(6,"translate"),t.ɵɵelementStart(7,"mat-icon",3),t.ɵɵpipe(8,"translate"),t.ɵɵtext(9," help "),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.copyKeysConfigForm),t.ɵɵadvance(),t.ɵɵproperty("labelText",t.ɵɵpipeBind1(2,7,"tb.key-val.copy-key-values-from"))("translation",n.translation),t.ɵɵadvance(2),t.ɵɵproperty("label",t.ɵɵpipeBind1(4,9,"tb.rulenode.keys"))("placeholder",t.ɵɵpipeBind1(5,11,"tb.rulenode.add-key"))("requiredText",t.ɵɵpipeBind1(6,13,"tb.key-val.at-least-one-key-error")),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(8,15,"tb.rulenode.use-regular-expression-hint")))},dependencies:t.ɵɵgetComponentDepsFactory(Ep),encapsulation:2})}}function Fp(e,n){if(1&e&&(t.ɵɵelementStart(0,"tb-toggle-option",7),t.ɵɵtext(1),t.ɵɵelementEnd()),2&e){const e=n.$implicit;t.ɵɵproperty("value",e.value),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",e.name," ")}}e("CopyKeysConfigComponent",Ep);class qp extends i{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.renameIn=[],this.translation=zt;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,[N.required]],renameKeysMapping:[e?e.renameKeysMapping:null,[N.required]]})}prepareInputConfig(e){let t;return t=P(e?.fromMetadata)?e.fromMetadata?Kt.METADATA:Kt.DATA:P(e?.renameIn)?e?.renameIn:Kt.DATA,{renameKeysMapping:P(e?.renameKeysMapping)?e.renameKeysMapping:null,renameIn:t}}static{this.ɵfac=function(e){return new(e||qp)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:qp,selectors:[["tb-transformation-node-rename-keys-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:15,vars:24,consts:[[1,"tb-form-panel","stroked",3,"formGroup"],["translate","",1,"tb-form-panel-title"],[1,"fx-centered"],[1,"fetch-to-data-toggle"],["formControlName","renameIn","appearance","fill",1,"fetch-to-data-toggle"],[3,"value",4,"ngFor","ngForOf"],["required","","formControlName","renameKeysMapping","uniqueKeyValuePairValidator","",3,"labelText","requiredText","keyText","keyRequiredText","valText","valRequiredText"],[3,"value"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1),t.ɵɵtext(2,"tb.rulenode.rename-keys-in"),t.ɵɵelementEnd(),t.ɵɵelementStart(3,"div",2)(4,"div",3)(5,"tb-toggle-select",4),t.ɵɵtemplate(6,Fp,2,2,"tb-toggle-option",5),t.ɵɵelementEnd()()(),t.ɵɵelement(7,"tb-kv-map-config",6),t.ɵɵpipe(8,"translate"),t.ɵɵpipe(9,"translate"),t.ɵɵpipe(10,"translate"),t.ɵɵpipe(11,"translate"),t.ɵɵpipe(12,"translate"),t.ɵɵpipe(13,"translate"),t.ɵɵpipe(14,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.renameKeysConfigForm),t.ɵɵadvance(6),t.ɵɵproperty("ngForOf",n.renameIn),t.ɵɵadvance(),t.ɵɵpropertyInterpolate2("labelText","",t.ɵɵpipeBind1(8,10,n.translation.get(n.renameKeysConfigForm.get("renameIn").value))," ",t.ɵɵpipeBind1(9,12,"tb.rulenode.keys-mapping"),""),t.ɵɵpropertyInterpolate("requiredText",t.ɵɵpipeBind1(10,14,"tb.rulenode.attr-mapping-required")),t.ɵɵpropertyInterpolate("keyText",t.ɵɵpipeBind1(11,16,"tb.rulenode.current-key-name")),t.ɵɵpropertyInterpolate("keyRequiredText",t.ɵɵpipeBind1(12,18,"tb.rulenode.key-name-required")),t.ɵɵpropertyInterpolate("valText",t.ɵɵpipeBind1(13,20,"tb.rulenode.new-key-name")),t.ɵɵpropertyInterpolate("valRequiredText",t.ɵɵpipeBind1(14,22,"tb.rulenode.new-key-name-required")))},dependencies:t.ɵɵgetComponentDepsFactory(qp),styles:["[_nghost-%COMP%] .fetch-to-data-toggle[_ngcontent-%COMP%]{max-width:420px;width:100%}[_nghost-%COMP%] .fx-centered[_ngcontent-%COMP%]{display:flex;width:100%;justify-content:space-around}"]})}}function Ap(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(2,1,"tb.rulenode.json-path-expression-required")))}e("RenameKeysConfigComponent",qp);class kp extends i{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,[N.required]]})}static{this.ɵfac=function(e){return new(e||kp)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:kp,selectors:[["tb-transformation-node-json-path-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:10,vars:8,consts:[[3,"formGroup"],["subscriptSizing","dynamic",1,"mat-block"],["matInput","","formControlName","jsonPath","required",""],[4,"ngIf"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label"),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(5,"input",2),t.ɵɵelementStart(6,"mat-hint"),t.ɵɵtext(7),t.ɵɵpipe(8,"translate"),t.ɵɵelementEnd(),t.ɵɵtemplate(9,Ap,3,3,"mat-error",3),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.jsonPathConfigForm),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(4,4,"tb.rulenode.json-path-expression")),t.ɵɵadvance(4),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(8,6,"tb.rulenode.json-path-expression-hint")),t.ɵɵadvance(2),t.ɵɵproperty("ngIf",n.jsonPathConfigForm.get("jsonPath").hasError("required")))},dependencies:t.ɵɵgetComponentDepsFactory(kp),encapsulation:2})}}e("NodeJsonPathConfigComponent",kp);class Np extends i{constructor(e,t,n){super(e),this.store=e,this.fb=t,this.translate=n,this.deleteFrom=[],this.translation=Ht;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,[N.required]],keys:[e?e.keys:null,[N.required]]})}prepareInputConfig(e){let t;return t=P(e?.fromMetadata)?e.fromMetadata?Kt.METADATA:Kt.DATA:P(e?.deleteFrom)?e?.deleteFrom:Kt.DATA,{keys:P(e?.keys)?e.keys:null,deleteFrom:t}}configForm(){return this.deleteKeysConfigForm}static{this.ɵfac=function(e){return new(e||Np)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder),t.ɵɵdirectiveInject(K.TranslateService))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Np,selectors:[["tb-transformation-node-delete-keys-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:10,vars:16,consts:[[1,"tb-form-panel","no-border","no-padding",3,"formGroup"],["formControlName","deleteFrom",3,"labelText"],["required","","formControlName","keys",1,"mat-block",3,"label","placeholder","requiredText"],["matSuffix","","aria-hidden","false","aria-label","help-icon","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0),t.ɵɵelement(1,"tb-msg-metadata-chip",1),t.ɵɵpipe(2,"translate"),t.ɵɵelementStart(3,"tb-string-items-list",2),t.ɵɵpipe(4,"translate"),t.ɵɵpipe(5,"translate"),t.ɵɵpipe(6,"translate"),t.ɵɵelementStart(7,"mat-icon",3),t.ɵɵpipe(8,"translate"),t.ɵɵtext(9," help "),t.ɵɵelementEnd()()()),2&e&&(t.ɵɵproperty("formGroup",n.deleteKeysConfigForm),t.ɵɵadvance(),t.ɵɵproperty("labelText",t.ɵɵpipeBind1(2,6,"tb.key-val.delete-key-values-from")),t.ɵɵadvance(2),t.ɵɵproperty("label",t.ɵɵpipeBind1(4,8,"tb.rulenode.keys"))("placeholder",t.ɵɵpipeBind1(5,10,"tb.rulenode.add-key"))("requiredText",t.ɵɵpipeBind1(6,12,"tb.key-val.at-least-one-key-error")),t.ɵɵadvance(4),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(8,14,"tb.rulenode.use-regular-expression-delete-hint")))},dependencies:t.ɵɵgetComponentDepsFactory(Np),encapsulation:2})}}function wp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.interval-required")," "))}function Mp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.interval-min-error")," "))}function Bp(e,n){if(1&e&&(t.ɵɵelementStart(0,"tb-toggle-option",18),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e){const e=n.$implicit,r=t.ɵɵnextContext();t.ɵɵproperty("value",e),t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,2,r.deduplicationStrategiesTranslations.get(e))," ")}}function Vp(e,n){1&e&&(t.ɵɵelement(0,"tb-example-hint",19),t.ɵɵpipe(1,"translate")),2&e&&t.ɵɵproperty("hintText",t.ɵɵpipeBind1(1,1,"tb.rulenode.strategy-all-hint"))}function Op(e,n){1&e&&(t.ɵɵelement(0,"tb-example-hint",20),t.ɵɵpipe(1,"translate")),2&e&&t.ɵɵproperty("hintText",t.ɵɵpipeBind1(1,1,"tb.rulenode.strategy-first-hint"))}function Dp(e,n){1&e&&(t.ɵɵelement(0,"tb-example-hint",20),t.ɵɵpipe(1,"translate")),2&e&&t.ɵɵproperty("hintText",t.ɵɵpipeBind1(1,1,"tb.rulenode.strategy-last-hint"))}function Lp(e,n){1&e&&(t.ɵɵelementStart(0,"div"),t.ɵɵelement(1,"tb-output-message-type-autocomplete",21),t.ɵɵelementEnd())}function Pp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-pending-msgs-required")," "))}function Rp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-pending-msgs-max-error")," "))}function _p(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-pending-msgs-min-error")," "))}function jp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-retries-required")," "))}function Gp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-retries-max-error")," "))}function Kp(e,n){1&e&&(t.ɵɵelementStart(0,"mat-error"),t.ɵɵtext(1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵadvance(),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(2,1,"tb.rulenode.max-retries-min-error")," "))}e("DeleteKeysConfigComponent",Np);class Up extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.deduplicationStrategie=St,this.deduplicationStrategies=Object.keys(this.deduplicationStrategie),this.deduplicationStrategiesTranslations=Tt}configForm(){return this.deduplicationConfigForm}onConfigurationSet(e){this.deduplicationConfigForm=this.fb.group({interval:[P(e?.interval)?e.interval:null,[N.required,N.min(1)]],strategy:[P(e?.strategy)?e.strategy:null,[N.required]],outMsgType:[P(e?.outMsgType)?e.outMsgType:null,[N.required]],maxPendingMsgs:[P(e?.maxPendingMsgs)?e.maxPendingMsgs:null,[N.required,N.min(1),N.max(1e3)]],maxRetries:[P(e?.maxRetries)?e.maxRetries:null,[N.required,N.min(0),N.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"]}static{this.ɵfac=function(e){return new(e||Up)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.FormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Up,selectors:[["tb-action-node-msg-deduplication-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:49,vars:32,consts:[[3,"formGroup"],[1,"mat-block"],["type","number","required","","matInput","","formControlName","interval"],[4,"ngIf"],["matSuffix","","aria-hidden","false","aria-label","help-icon","color","primary",1,"help-icon","margin-8","cursor-pointer",3,"matTooltip"],[1,"tb-form-panel","no-padding","no-border"],[1,"tb-form-panel","stroked"],["translate","",1,"tb-form-panel-title","tb-required"],["formControlName","strategy","appearance","fill",1,"fetch-to-data-toggle"],[3,"value",4,"ngFor","ngForOf"],[3,"hintText",4,"ngIf"],["textAlign","'center'",3,"hintText",4,"ngIf"],[1,"tb-settings"],["translate",""],[1,"tb-form-row","no-border","no-padding","tb-standard-fields"],[1,"flex"],["type","number","required","","matInput","","formControlName","maxPendingMsgs"],["type","number","required","","matInput","","formControlName","maxRetries"],[3,"value"],[3,"hintText"],["textAlign","'center'",3,"hintText"],["required","","formControlName","outMsgType"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"mat-form-field",1)(2,"mat-label"),t.ɵɵtext(3),t.ɵɵpipe(4,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(5,"input",2),t.ɵɵtemplate(6,wp,3,3,"mat-error",3)(7,Mp,3,3,"mat-error",3),t.ɵɵelementStart(8,"mat-icon",4),t.ɵɵpipe(9,"translate"),t.ɵɵtext(10,"help"),t.ɵɵelementEnd()(),t.ɵɵelementStart(11,"div",5)(12,"div",6)(13,"div",7),t.ɵɵtext(14,"tb.rulenode.strategy"),t.ɵɵelementEnd(),t.ɵɵelementStart(15,"tb-toggle-select",8),t.ɵɵtemplate(16,Bp,3,4,"tb-toggle-option",9),t.ɵɵelementEnd(),t.ɵɵtemplate(17,Vp,2,3,"tb-example-hint",10)(18,Op,2,3,"tb-example-hint",11)(19,Dp,2,3,"tb-example-hint",11)(20,Lp,2,0,"div",3),t.ɵɵelementEnd(),t.ɵɵelementStart(21,"section",6)(22,"mat-expansion-panel",12)(23,"mat-expansion-panel-header")(24,"mat-panel-title",13),t.ɵɵtext(25,"tb.rulenode.advanced-settings"),t.ɵɵelementEnd()(),t.ɵɵelementStart(26,"div",14)(27,"mat-form-field",15)(28,"mat-label"),t.ɵɵtext(29),t.ɵɵpipe(30,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(31,"input",16),t.ɵɵtemplate(32,Pp,3,3,"mat-error",3)(33,Rp,3,3,"mat-error",3)(34,_p,3,3,"mat-error",3),t.ɵɵelementStart(35,"mat-icon",4),t.ɵɵpipe(36,"translate"),t.ɵɵtext(37,"help"),t.ɵɵelementEnd()(),t.ɵɵelementStart(38,"mat-form-field",15)(39,"mat-label"),t.ɵɵtext(40),t.ɵɵpipe(41,"translate"),t.ɵɵelementEnd(),t.ɵɵelement(42,"input",17),t.ɵɵtemplate(43,jp,3,3,"mat-error",3)(44,Gp,3,3,"mat-error",3)(45,Kp,3,3,"mat-error",3),t.ɵɵelementStart(46,"mat-icon",4),t.ɵɵpipe(47,"translate"),t.ɵɵtext(48,"help"),t.ɵɵelementEnd()()()()()()()),2&e&&(t.ɵɵproperty("formGroup",n.deduplicationConfigForm),t.ɵɵadvance(3),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(4,20,"tb.rulenode.interval")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.deduplicationConfigForm.get("interval").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.deduplicationConfigForm.get("interval").hasError("min")),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(9,22,"tb.rulenode.interval-hint")),t.ɵɵadvance(8),t.ɵɵproperty("ngForOf",n.deduplicationStrategies),t.ɵɵadvance(),t.ɵɵproperty("ngIf","ALL"===n.deduplicationConfigForm.get("strategy").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf","FIRST"===n.deduplicationConfigForm.get("strategy").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf","LAST"===n.deduplicationConfigForm.get("strategy").value),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.deduplicationConfigForm.get("strategy").value===n.deduplicationStrategie.ALL),t.ɵɵadvance(9),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(30,24,"tb.rulenode.max-pending-msgs")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.deduplicationConfigForm.get("maxPendingMsgs").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.deduplicationConfigForm.get("maxPendingMsgs").hasError("max")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.deduplicationConfigForm.get("maxPendingMsgs").hasError("min")),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(36,26,"tb.rulenode.max-pending-msgs-hint")),t.ɵɵadvance(5),t.ɵɵtextInterpolate(t.ɵɵpipeBind1(41,28,"tb.rulenode.max-retries")),t.ɵɵadvance(3),t.ɵɵproperty("ngIf",n.deduplicationConfigForm.get("maxRetries").hasError("required")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.deduplicationConfigForm.get("maxRetries").hasError("max")),t.ɵɵadvance(),t.ɵɵproperty("ngIf",n.deduplicationConfigForm.get("maxRetries").hasError("min")),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("matTooltip",t.ɵɵpipeBind1(47,30,"tb.rulenode.max-retries-hint")))},dependencies:t.ɵɵgetComponentDepsFactory(Up),encapsulation:2})}}e("DeduplicationConfigComponent",Up);class Hp{static{this.ɵfac=function(e){return new(e||Hp)}}static{this.ɵmod=t.ɵɵdefineNgModule({type:Hp})}static{this.ɵinj=t.ɵɵdefineInjector({imports:[$,S,xi,sp,gp,Ip,Ep,qp,kp,Np,Up]})}}e("RulenodeCoreConfigTransformModule",Hp),("undefined"==typeof ngJitMode||ngJitMode)&&t.ɵɵsetNgModuleScope(Hp,{declarations:[sp,gp,Ip,Ep,qp,kp,Np,Up],imports:[$,S,xi],exports:[sp,gp,Ip,Ep,qp,kp,Np,Up]});const zp=e=>[e];class $p extends i{constructor(e,t){super(e),this.store=e,this.fb=t,this.entityType=u}configForm(){return this.ruleChainInputConfigForm}onConfigurationSet(e){this.ruleChainInputConfigForm=this.fb.group({forwardMsgToDefaultRuleChain:[!!e&&e?.forwardMsgToDefaultRuleChain,[]],ruleChainId:[e?e.ruleChainId:null,[N.required]]})}static{this.ɵfac=function(e){return new(e||$p)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:$p,selectors:[["tb-flow-node-rule-chain-input-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:8,vars:12,consts:[[1,"flex","flex-col",3,"formGroup"],[1,"tb-form-panel","no-padding","no-border"],[1,"tb-form-row","no-border",3,"tb-hint-tooltip-icon"],["formControlName","forwardMsgToDefaultRuleChain",1,"mat-slide"],["required","","formControlName","ruleChainId",3,"excludeEntityIds","entityType","entitySubtype"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0)(1,"div",1)(2,"div",2),t.ɵɵpipe(3,"translate"),t.ɵɵelementStart(4,"mat-slide-toggle",3),t.ɵɵtext(5),t.ɵɵpipe(6,"translate"),t.ɵɵelementEnd()(),t.ɵɵelement(7,"tb-entity-autocomplete",4),t.ɵɵelementEnd()()),2&e&&(t.ɵɵproperty("formGroup",n.ruleChainInputConfigForm),t.ɵɵadvance(2),t.ɵɵpropertyInterpolate("tb-hint-tooltip-icon",t.ɵɵpipeBind1(3,6,"tb.rulenode.forward-msg-default-rule-chain-tooltip")),t.ɵɵadvance(3),t.ɵɵtextInterpolate1(" ",t.ɵɵpipeBind1(6,8,"tb.rulenode.forward-msg-default-rule-chain")," "),t.ɵɵadvance(2),t.ɵɵproperty("excludeEntityIds",t.ɵɵpureFunction1(10,zp,n.ruleChainId))("entityType",n.entityType.RULE_CHAIN)("entitySubtype",n.ruleChainType))},dependencies:t.ɵɵgetComponentDepsFactory($p),encapsulation:2})}}e("RuleChainInputComponent",$p);class Qp extends i{constructor(e,t){super(e),this.store=e,this.fb=t}configForm(){return this.ruleChainOutputConfigForm}onConfigurationSet(e){this.ruleChainOutputConfigForm=this.fb.group({})}static{this.ɵfac=function(e){return new(e||Qp)(t.ɵɵdirectiveInject(A.Store),t.ɵɵdirectiveInject(k.UntypedFormBuilder))}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Qp,selectors:[["tb-flow-node-rule-chain-output-config"]],features:[t.ɵɵInheritDefinitionFeature],decls:3,vars:4,consts:[[1,"flex","flex-col",3,"formGroup"],[3,"innerHTML"]],template:function(e,n){1&e&&(t.ɵɵelementStart(0,"section",0),t.ɵɵelement(1,"div",1),t.ɵɵpipe(2,"translate"),t.ɵɵelementEnd()),2&e&&(t.ɵɵproperty("formGroup",n.ruleChainOutputConfigForm),t.ɵɵadvance(),t.ɵɵpropertyInterpolate("innerHTML",t.ɵɵpipeBind1(2,2,"tb.rulenode.output-node-name-hint"),t.ɵɵsanitizeHtml))},dependencies:t.ɵɵgetComponentDepsFactory(Qp),encapsulation:2})}}e("RuleChainOutputComponent",Qp);class Jp{static{this.ɵfac=function(e){return new(e||Jp)}}static{this.ɵmod=t.ɵɵdefineNgModule({type:Jp})}static{this.ɵinj=t.ɵɵdefineInjector({imports:[$,S,xi,$p,Qp]})}}e("RuleNodeCoreConfigFlowModule",Jp),("undefined"==typeof ngJitMode||ngJitMode)&&t.ɵɵsetNgModuleScope(Jp,{declarations:[$p,Qp],imports:[$,S,xi],exports:[$p,Qp]});class Yp{constructor(){}static{this.ɵfac=function(e){return new(e||Yp)}}static{this.ɵcmp=t.ɵɵdefineComponent({type:Yp,selectors:[["tb-lib-styles-entry"]],standalone:!0,features:[t.ɵɵStandaloneFeature],decls:0,vars:0,template:function(e,t){},styles:['.tb-default tb-rule-node-config .margin-8{margin:8px}.tb-default tb-rule-node-config .tb-error{letter-spacing:.25px;color:var(--mdc-theme-error, #f44336)}.tb-default tb-rule-node-config .tb-required:after{content:"*";font-size:16px;color:#000000de}.tb-default tb-rule-node-config .help-icon{color:#000;opacity:.38;padding:unset}.tb-default tb-rule-node-config .help-icon:hover{color:#305680;opacity:unset}.tb-default tb-rule-node-config .same-width-component-row{display:flex;flex-wrap:nowrap;gap:16px}@media screen and (max-width: 599px){.tb-default tb-rule-node-config .same-width-component-row{gap:8px}}.tb-default tb-rule-node-config .same-width-component-row>*{flex:1}.tb-default .gap-0{gap:0px}.tb-default .gap-5\\.5{gap:1.375rem}@media (max-width: 599px){.tb-default .xs\\:max-h-full{max-height:100%}}@media (min-width: 960px) and (max-width: 1279px){.tb-default .md\\:max-h-full{max-height:100%}}@media (max-width: 959px){.tb-default .lt-md\\:gap-4{gap:1rem}}@media (min-width: 960px){.tb-default .gt-sm\\:max-w-10{max-width:2.5rem}.tb-default .gt-sm\\:max-w-10\\%{max-width:10%}.tb-default .gt-sm\\:gap-4{gap:1rem}.tb-default .gt-sm\\:gap-5\\.5{gap:1.375rem}}\n'],encapsulation:2})}}const Wp=(e,t)=>{const n=e[a];if(n.styles?.length){const e=n.styles[0];let r=document.getElementById(t);if(!r){r=document.createElement("style"),r.id=t;(document.head||document.getElementsByTagName("head")[0]).appendChild(r)}r.innerHTML=e}};class Xp{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.","max-relation-level-invalid":"Value should be an integer.","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","fields-mapping-hint":"If the message field is set to $entityId, the message originator's id will be saved to the specified table column.","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.","default-ttl-zero-hint":"TTL will not be applied if its value is set to 0.","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":"Period in seconds","period-seconds-required":"Period is required.","generation-frequency-seconds":"Generation frequency in seconds","generation-frequency-required":"Generation frequency is required.","min-generation-frequency-message":"Only 1 second minimum is allowed.","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","current-tenant":"Current Tenant","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.","memory-buffer-size-range":"Memory buffer size must be between 0 and {{max}} KB",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.","int-range":"Value must not exceed the maximum integer limit (2147483648)","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":"The table must be created in your Cassandra cluster and its name must start with the prefix 'cs_tb_' to avoid the data insertion to the common TB tables. Enter the table name here without the 'cs_tb_' prefix.","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),Wp(Yp,"tb-rule-node-core-config-css")}static{this.ɵfac=function(e){return new(e||Xp)(t.ɵɵinject(K.TranslateService))}}static{this.ɵmod=t.ɵɵdefineNgModule({type:Xp})}static{this.ɵinj=t.ɵɵdefineInjector({imports:[$,S,Ci,np,bo,hs,Hp,Jp,oe]})}}e("RuleNodeCoreConfigModule",Xp),("undefined"==typeof ngJitMode||ngJitMode)&&t.ɵɵsetNgModuleScope(Xp,{declarations:[oe],imports:[$,S],exports:[Ci,np,bo,hs,Hp,Jp,oe]})}}}));//# sourceMappingURL=rulenode-core-config.js.map From 0de04791775d529187366278d2c86b455661711e Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Thu, 9 Jan 2025 13:04:40 +0200 Subject: [PATCH 05/13] UI: Add lazy-load rulechain page components --- .../src/app/core/http/rule-chain.service.ts | 10 +++- .../rule-node/rule-node-config.module.ts | 26 +++++---- .../home/pages/edge/edge-routing.module.ts | 3 + .../rulechain/rule-node-config.component.ts | 10 +--- .../pages/rulechain/rulechain-page.module.ts | 57 +++++++++++++++++++ .../rulechain/rulechain-routing.module.ts | 2 + .../home/pages/rulechain/rulechain.module.ts | 25 +------- 7 files changed, 89 insertions(+), 44 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts diff --git a/ui-ngx/src/app/core/http/rule-chain.service.ts b/ui-ngx/src/app/core/http/rule-chain.service.ts index e3353989cc..37a9f8c1af 100644 --- a/ui-ngx/src/app/core/http/rule-chain.service.ts +++ b/ui-ngx/src/app/core/http/rule-chain.service.ts @@ -53,6 +53,7 @@ export class RuleChainService { private ruleNodeComponentsMap: Map> = new Map>(); private ruleNodeConfigComponents: {[directive: string]: Type} = {}; + private systemRuleNodeConfigComponents: {[directive: string]: Type} = {}; constructor( private http: HttpClient, @@ -128,7 +129,10 @@ export class RuleChainService { } } - public getRuleNodeConfigComponent(directive: string): Type { + public getRuleNodeConfigComponent(directive: string, isSystemComponent = false): Type { + if (isSystemComponent) { + return this.systemRuleNodeConfigComponents[directive]; + } return this.ruleNodeConfigComponents[directive]; } @@ -180,6 +184,10 @@ export class RuleChainService { return this.http.post(url, inputParams, defaultHttpOptionsFromConfig(config)); } + public registemSystemRuleNodeConfigComponent(componentMap: Record>) { + this.systemRuleNodeConfigComponents = componentMap; + } + private loadRuleNodeComponents(ruleChainType: RuleChainType, config?: RequestConfig): Observable> { return this.componentDescriptorService.getComponentDescriptorsByTypes(ruleNodeTypeComponentTypes, ruleChainType, config).pipe( map((components) => { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts index 58efd925db..f960777220 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts @@ -43,6 +43,7 @@ import { FlowRuleNodeConfigModule } from '@home/components/rule-node/flow/flow-rule-node-config.module'; import { IRuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { RuleChainService } from '@core/http/rule-chain.service'; @NgModule({ declarations: [ @@ -62,14 +63,17 @@ import { IRuleNodeConfigurationComponent } from '@shared/models/rule-node.models EmptyConfigComponent ] }) -export class RuleNodeConfigModule {} - -export const ruleNodeConfigComponentsMap: Record> = { - ...actionRuleNodeConfigComponentsMap, - ...enrichmentRuleNodeConfigComponentsMap, - ...externalRuleNodeConfigComponentsMap, - ...filterRuleNodeConfigComponentsMap, - ...flowRuleNodeConfigComponentsMap, - ...transformationRuleNodeConfigComponentsMap, - 'tbNodeEmptyConfig': EmptyConfigComponent -}; +export class RuleNodeConfigModule { + constructor(private ruleChainService: RuleChainService) { + const ruleNodeConfigComponentsMap: Record> = { + ...actionRuleNodeConfigComponentsMap, + ...enrichmentRuleNodeConfigComponentsMap, + ...externalRuleNodeConfigComponentsMap, + ...filterRuleNodeConfigComponentsMap, + ...flowRuleNodeConfigComponentsMap, + ...transformationRuleNodeConfigComponentsMap, + 'tbNodeEmptyConfig': EmptyConfigComponent + }; + this.ruleChainService.registemSystemRuleNodeConfigComponent(ruleNodeConfigComponentsMap); + } +} diff --git a/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts b/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts index 1302bfa140..bef4cd4a51 100644 --- a/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/edge/edge-routing.module.ts @@ -291,6 +291,7 @@ const routes: Routes = [ import: false, ruleChainType: RuleChainType.EDGE }, + loadChildren: () => import('../rulechain/rulechain-page.module').then(m => m.RuleChainPageModule), resolve: { ruleChain: RuleChainResolver, ruleChainMetaData: RuleChainMetaDataResolver, @@ -336,6 +337,7 @@ const routes: Routes = [ import: false, ruleChainType: RuleChainType.EDGE }, + loadChildren: () => import('../rulechain/rulechain-page.module').then(m => m.RuleChainPageModule), resolve: { ruleChain: RuleChainResolver, ruleChainMetaData: RuleChainMetaDataResolver, @@ -358,6 +360,7 @@ const routes: Routes = [ import: true, ruleChainType: RuleChainType.EDGE }, + loadChildren: () => import('../rulechain/rulechain-page.module').then(m => m.RuleChainPageModule), resolve: { ruleNodeComponents: RuleNodeComponentsResolver, tooltipster: TooltipsterResolver diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts index 029c4b5547..f6ed94991c 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts @@ -21,7 +21,7 @@ import { forwardRef, Input, OnDestroy, - Output, Type, + Output, ViewChild, ViewContainerRef } from '@angular/core'; @@ -43,7 +43,6 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { JsonObjectEditComponent } from '@shared/components/json-object-edit.component'; import { deepClone } from '@core/utils'; import { RuleChainType } from '@shared/models/rule-chain.models'; -import { ruleNodeConfigComponentsMap } from '@home/components/rule-node/rule-node-config.module'; @Component({ selector: 'tb-rule-node-config', @@ -213,12 +212,7 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnDestroy this.changeScriptSubscription = null; } this.definedConfigContainer.clear(); - let component: Type; - if (!this.nodeDefinition.uiResources?.length) { - component = ruleNodeConfigComponentsMap[this.nodeDefinition.configDirective]; - } else { - component = this.ruleChainService.getRuleNodeConfigComponent(this.nodeDefinition.configDirective); - } + const component = this.ruleChainService.getRuleNodeConfigComponent(this.nodeDefinition.configDirective, !this.nodeDefinition.uiResources?.length); this.definedConfigComponentRef = this.definedConfigContainer.createComponent(component); this.definedConfigComponent = this.definedConfigComponentRef.instance; this.definedConfigComponent.ruleNodeId = this.ruleNodeId; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts new file mode 100644 index 0000000000..5e2596939e --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts @@ -0,0 +1,57 @@ +/// +/// 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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { SharedModule } from '@shared/shared.module'; +import { HomeComponentsModule } from '@home/components/home-components.module'; +import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe'; +import { + EntityDebugSettingsButtonComponent +} from '@home/components/entity/debug/entity-debug-settings-button.component'; +import { RuleNodeConfigModule } from '@home/components/rule-node/rule-node-config.module'; +import { + AddRuleNodeDialogComponent, + AddRuleNodeLinkDialogComponent, + CreateNestedRuleChainDialogComponent, + RuleChainPageComponent +} from '@home/pages/rulechain/rulechain-page.component'; +import { RuleNodeDetailsComponent } from '@home/pages/rulechain/rule-node-details.component'; +import { RuleNodeConfigComponent } from '@home/pages/rulechain/rule-node-config.component'; +import { LinkLabelsComponent } from '@home/pages/rulechain/link-labels.component'; +import { RuleNodeLinkComponent } from '@home/pages/rulechain/rule-node-link.component'; + +@NgModule({ + declarations: [ + RuleChainPageComponent, + RuleNodeDetailsComponent, + LinkLabelsComponent, + RuleNodeLinkComponent, + RuleNodeConfigComponent, + AddRuleNodeLinkDialogComponent, + AddRuleNodeDialogComponent, + CreateNestedRuleChainDialogComponent + ], + imports: [ + CommonModule, + SharedModule, + DurationLeftPipe, + EntityDebugSettingsButtonComponent, + RuleNodeConfigModule, + HomeComponentsModule, + ] +}) +export class RuleChainPageModule {} diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts index 0162e43655..cff4d2df4e 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-routing.module.ts @@ -148,6 +148,7 @@ const routes: Routes = [ import: false, ruleChainType: RuleChainType.CORE }, + loadChildren: () => import('./rulechain-page.module').then(m => m.RuleChainPageModule), resolve: { ruleChain: RuleChainResolver, ruleChainMetaData: RuleChainMetaDataResolver, @@ -170,6 +171,7 @@ const routes: Routes = [ import: true, ruleChainType: RuleChainType.CORE }, + loadChildren: () => import('./rulechain-page.module').then(m => m.RuleChainPageModule), resolve: { ruleNodeComponents: RuleNodeComponentsResolver, tooltipster: TooltipsterResolver diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.module.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.module.ts index 00fa560382..be9478574d 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.module.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain.module.ts @@ -21,34 +21,14 @@ import { RuleChainComponent } from '@modules/home/pages/rulechain/rulechain.comp import { RuleChainRoutingModule } from '@modules/home/pages/rulechain/rulechain-routing.module'; import { HomeComponentsModule } from '@modules/home/components/home-components.module'; import { RuleChainTabsComponent } from '@home/pages/rulechain/rulechain-tabs.component'; -import { - AddRuleNodeDialogComponent, - AddRuleNodeLinkDialogComponent, CreateNestedRuleChainDialogComponent, - RuleChainPageComponent -} from './rulechain-page.component'; import { RuleNodeComponent } from '@home/pages/rulechain/rulenode.component'; import { FC_NODE_COMPONENT_CONFIG } from 'ngx-flowchart'; -import { RuleNodeDetailsComponent } from './rule-node-details.component'; -import { RuleNodeLinkComponent } from './rule-node-link.component'; -import { LinkLabelsComponent } from '@home/pages/rulechain/link-labels.component'; -import { RuleNodeConfigComponent } from './rule-node-config.component'; -import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe'; -import { EntityDebugSettingsButtonComponent } from '@home/components/entity/debug/entity-debug-settings-button.component'; -import { RuleNodeConfigModule } from '@home/components/rule-node/rule-node-config.module'; @NgModule({ declarations: [ RuleChainComponent, RuleChainTabsComponent, - RuleChainPageComponent, RuleNodeComponent, - RuleNodeDetailsComponent, - RuleNodeConfigComponent, - LinkLabelsComponent, - RuleNodeLinkComponent, - AddRuleNodeLinkDialogComponent, - AddRuleNodeDialogComponent, - CreateNestedRuleChainDialogComponent ], providers: [ { @@ -56,16 +36,13 @@ import { RuleNodeConfigModule } from '@home/components/rule-node/rule-node-confi useValue: { nodeComponentType: RuleNodeComponent } - } + }, ], imports: [ CommonModule, SharedModule, HomeComponentsModule, RuleChainRoutingModule, - DurationLeftPipe, - EntityDebugSettingsButtonComponent, - RuleNodeConfigModule, ] }) export class RuleChainModule { } From b8a8db3b3bc5479b56b1f0139fa359c51be46e45 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 14 Jan 2025 10:48:07 +0200 Subject: [PATCH 06/13] UI: Updated rule node config translate keys --- .../assign-customer-config.component.html | 8 +- .../action/attributes-config.component.html | 24 +- .../action/clear-alarm-config.component.html | 6 +- .../action/clear-alarm-config.component.ts | 4 +- .../action/create-alarm-config.component.html | 34 +- .../action/create-alarm-config.component.ts | 4 +- .../create-relation-config.component.html | 22 +- .../create-relation-config.component.ts | 18 +- .../delete-attributes-config.component.html | 24 +- .../delete-relation-config.component.html | 8 +- .../delete-relation-config.component.ts | 18 +- .../device-profile-config.component.html | 10 +- .../action/device-state-config.component.html | 2 +- .../action/generator-config.component.html | 26 +- .../action/generator-config.component.ts | 8 +- .../gps-geo-action-config.component.html | 76 +- .../rule-node/action/log-config.component.ts | 4 +- .../math-function-config.component.html | 32 +- .../action/msg-count-config.component.html | 10 +- .../action/msg-delay-config.component.html | 24 +- .../push-to-cloud-config.component.html | 8 +- .../action/push-to-edge-config.component.html | 8 +- .../action/rpc-reply-config.component.html | 10 +- .../action/rpc-request-config.component.html | 6 +- ...save-to-custom-table-config.component.html | 28 +- ...-rest-api-call-reply-config.component.html | 8 +- .../action/timeseries-config.component.html | 16 +- .../unassign-customer-config.component.html | 10 +- .../arguments-map-config.component.html | 24 +- .../common/credentials-config.component.html | 36 +- ...vice-relations-query-config.component.html | 20 +- .../common/example-hint.component.html | 2 +- .../common/kv-map-config-old.component.html | 6 +- .../common/kv-map-config.component.html | 8 +- .../math-function-autocomplete.component.html | 4 +- .../message-types-config.component.html | 10 +- .../common/message-types-config.component.ts | 2 +- ...t-message-type-autocomplete.component.html | 10 +- .../relations-query-config-old.component.html | 4 +- .../relations-query-config.component.html | 14 +- .../common/select-attributes.component.html | 24 +- .../common/sv-map-config.component.html | 6 +- .../calculate-delta-config.component.html | 44 +- .../customer-attributes-config.component.html | 18 +- .../device-attributes-config.component.html | 12 +- .../entity-details-config.component.html | 10 +- ...h-device-credentials-config.component.html | 2 +- ...emetry-from-database-config.component.html | 66 +- ...riginator-attributes-config.component.html | 10 +- .../originator-fields-config.component.html | 20 +- .../related-attributes-config.component.html | 30 +- .../tenant-attributes-config.component.html | 18 +- .../azure-iot-hub-config.component.html | 50 +- .../external/kafka-config.component.html | 58 +- .../external/lambda-config.component.html | 48 +- .../external/mqtt-config.component.html | 44 +- .../external/pubsub-config.component.html | 26 +- .../external/rabbit-mq-config.component.html | 44 +- .../rest-api-call-config.component.html | 66 +- .../external/send-email-config.component.html | 50 +- .../external/send-sms-config.component.html | 14 +- .../external/slack-config.component.html | 12 +- .../external/sns-config.component.html | 18 +- .../external/sqs-config.component.html | 38 +- .../filter/check-alarm-status.component.html | 4 +- .../check-message-config.component.html | 20 +- .../check-relation-config.component.html | 8 +- .../gps-geo-filter-config.component.html | 50 +- .../filter/message-type-config.component.html | 2 +- .../originator-type-config.component.html | 8 +- .../filter/script-config.component.ts | 4 +- .../filter/switch-config.component.ts | 4 +- .../flow/rule-chain-input.component.html | 4 +- .../flow/rule-chain-output.component.html | 2 +- .../rule-node/rule-node-config.models.ts | 188 +-- .../change-originator-config.component.html | 8 +- .../copy-keys-config.component.html | 10 +- .../deduplication-config.component.html | 38 +- .../delete-keys-config.component.html | 10 +- .../node-json-path-config.component.html | 6 +- .../rename-keys-config.component.html | 14 +- .../transformation/script-config.component.ts | 4 +- .../to-email-config.component.html | 40 +- .../to-email-config.component.ts | 12 +- .../assets/locale/locale.constant-en_US.json | 1463 +++++++++-------- 85 files changed, 1615 insertions(+), 1608 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.html index 486764f936..4ec27d83e7 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/assign-customer-config.component.html @@ -18,17 +18,17 @@
    - tb.rulenode.customer-name-pattern + rule-node-config.customer-name-pattern - {{ 'tb.rulenode.customer-name-pattern-required' | translate }} + {{ 'rule-node-config.customer-name-pattern-required' | translate }} - tb.rulenode.customer-name-pattern-hint + rule-node-config.customer-name-pattern-hint
    - {{ 'tb.rulenode.create-customer-if-not-exists' | translate }} + {{ 'rule-node-config.create-customer-if-not-exists' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.html index 80633ca0d3..258f856e91 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.html @@ -17,11 +17,11 @@ -->
    - +
    - {{ 'tb.rulenode.attributes-scope' | translate }} + {{ 'rule-node-config.attributes-scope' | translate }} @@ -30,7 +30,7 @@ - {{ 'tb.rulenode.attributes-scope-value' | translate }} + {{ 'rule-node-config.attributes-scope-value' | translate }}
    - tb.rulenode.alarm-type + rule-node-config.alarm-type - {{ 'tb.rulenode.alarm-type-required' | translate }} + {{ 'rule-node-config.alarm-type-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts index f132d737eb..cf96982621 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/clear-alarm-config.component.ts @@ -47,7 +47,7 @@ export class ClearAlarmConfigComponent extends RuleNodeConfigurationComponent { readonly hasScript = true; - readonly testScriptLabel = 'tb.rulenode.test-details-function'; + readonly testScriptLabel = 'rule-node-config.test-details-function'; constructor(protected store: Store, private fb: UntypedFormBuilder, @@ -103,7 +103,7 @@ export class ClearAlarmConfigComponent extends RuleNodeConfigurationComponent { this.nodeScriptTestService.testNodeScript( script, 'json', - this.translate.instant('tb.rulenode.details'), + this.translate.instant('rule-node-config.details'), 'Details', ['msg', 'metadata', 'msgType'], this.ruleNodeId, diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.html index 9b1efd0f1a..9ec4238081 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.html @@ -17,10 +17,10 @@ -->
    - {{ 'tb.rulenode.use-message-alarm-data' | translate }} + {{ 'rule-node-config.use-message-alarm-data' | translate }} - {{ 'tb.rulenode.overwrite-alarm-details' | translate }} + {{ 'rule-node-config.overwrite-alarm-details' | translate }}
    @@ -67,41 +67,41 @@
    - tb.rulenode.alarm-type + rule-node-config.alarm-type - {{ 'tb.rulenode.alarm-type-required' | translate }} + {{ 'rule-node-config.alarm-type-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint - {{ 'tb.rulenode.use-alarm-severity-pattern' | translate }} + {{ 'rule-node-config.use-alarm-severity-pattern' | translate }} - tb.rulenode.alarm-severity + rule-node-config.alarm-severity {{ alarmSeverityTranslationMap.get(severity) | translate }} - {{ 'tb.rulenode.alarm-severity-required' | translate }} + {{ 'rule-node-config.alarm-severity-required' | translate }} - tb.rulenode.alarm-severity-pattern + rule-node-config.alarm-severity-pattern - {{ 'tb.rulenode.alarm-severity-required' | translate }} + {{ 'rule-node-config.alarm-severity-required' | translate }} - + - {{ 'tb.rulenode.propagate' | translate }} + {{ 'rule-node-config.propagate' | translate }}
    - tb.rulenode.relation-types-list + rule-node-config.relation-types-list close - - tb.rulenode.relation-types-list-hint + rule-node-config.relation-types-list-hint
    - {{ 'tb.rulenode.propagate-to-owner' | translate }} + {{ 'rule-node-config.propagate-to-owner' | translate }} - {{ 'tb.rulenode.propagate-to-tenant' | translate }} + {{ 'rule-node-config.propagate-to-tenant' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts index b5639f15ac..a68eedfbfc 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts @@ -54,7 +54,7 @@ export class CreateAlarmConfigComponent extends RuleNodeConfigurationComponent { readonly hasScript = true; - readonly testScriptLabel = 'tb.rulenode.test-details-function'; + readonly testScriptLabel = 'rule-node-config.test-details-function'; constructor(protected store: Store, private fb: UntypedFormBuilder, @@ -143,7 +143,7 @@ export class CreateAlarmConfigComponent extends RuleNodeConfigurationComponent { this.nodeScriptTestService.testNodeScript( script, 'json', - this.translate.instant('tb.rulenode.details'), + this.translate.instant('rule-node-config.details'), 'Details', ['msg', 'metadata', 'msgType'], this.ruleNodeId, diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.html index abbdb99f53..362bb4d9b6 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.html @@ -17,7 +17,7 @@ -->
    -
    tb.rulenode.relation-parameters
    +
    rule-node-config.relation-parameters
    relation.direction @@ -35,7 +35,7 @@
    -
    tb.rulenode.target-entity
    +
    rule-node-config.target-entity
    - tb.rulenode.profile-name + rule-node-config.profile-name
    - -
    - {{ 'tb.rulenode.create-entity-if-not-exists' | translate }} + {{ 'rule-node-config.create-entity-if-not-exists' | translate }}
    - tb.rulenode.advanced-settings + rule-node-config.advanced-settings
    -
    - {{ 'tb.rulenode.remove-current-relations' | translate }} + {{ 'rule-node-config.remove-current-relations' | translate }}
    -
    - {{ 'tb.rulenode.change-originator-to-related-entity' | translate }} + {{ 'rule-node-config.change-originator-to-related-entity' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts index 53c8da3bd6..b48a530b57 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-relation-config.component.ts @@ -30,8 +30,8 @@ export class CreateRelationConfigComponent extends RuleNodeConfigurationComponen directionTypes = Object.keys(EntitySearchDirection); directionTypeTranslations = new Map( [ - [EntitySearchDirection.FROM, 'tb.rulenode.search-direction-from'], - [EntitySearchDirection.TO, 'tb.rulenode.search-direction-to'], + [EntitySearchDirection.FROM, 'rule-node-config.search-direction-from'], + [EntitySearchDirection.TO, 'rule-node-config.search-direction-to'], ] ); @@ -39,13 +39,13 @@ export class CreateRelationConfigComponent extends RuleNodeConfigurationComponen entityTypeNamePatternTranslation = new Map( [ - [EntityType.DEVICE, 'tb.rulenode.device-name-pattern'], - [EntityType.ASSET, 'tb.rulenode.asset-name-pattern'], - [EntityType.ENTITY_VIEW, 'tb.rulenode.entity-view-name-pattern'], - [EntityType.CUSTOMER, 'tb.rulenode.customer-title-pattern'], - [EntityType.USER, 'tb.rulenode.user-name-pattern'], - [EntityType.DASHBOARD, 'tb.rulenode.dashboard-name-pattern'], - [EntityType.EDGE, 'tb.rulenode.edge-name-pattern'] + [EntityType.DEVICE, 'rule-node-config.device-name-pattern'], + [EntityType.ASSET, 'rule-node-config.asset-name-pattern'], + [EntityType.ENTITY_VIEW, 'rule-node-config.entity-view-name-pattern'], + [EntityType.CUSTOMER, 'rule-node-config.customer-title-pattern'], + [EntityType.USER, 'rule-node-config.user-name-pattern'], + [EntityType.DASHBOARD, 'rule-node-config.dashboard-name-pattern'], + [EntityType.EDGE, 'rule-node-config.edge-name-pattern'] ] ); diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.html index 7050cae88a..0f62bec757 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.html @@ -17,11 +17,11 @@ -->
    - +
    - {{ 'tb.rulenode.attributes-scope' | translate }} + {{ 'rule-node-config.attributes-scope' | translate }} @@ -30,7 +30,7 @@ - {{ 'tb.rulenode.attributes-scope-value' | translate }} + {{ 'rule-node-config.attributes-scope-value' | translate }}
    - {{ 'tb.rulenode.attributes-keys' | translate }} + {{ 'rule-node-config.attributes-keys' | translate }} - {{ 'tb.rulenode.attributes-keys-required' | translate }} - tb.rulenode.general-pattern-hint + {{ 'rule-node-config.attributes-keys-required' | translate }} + rule-node-config.general-pattern-hint
    - tb.rulenode.advanced-settings + rule-node-config.advanced-settings -
    - {{ 'tb.rulenode.send-attributes-deleted-notification' | translate }} + {{ 'rule-node-config.send-attributes-deleted-notification' | translate }}
    -
    - {{ 'tb.rulenode.notify-device' | translate }} + {{ 'rule-node-config.notify-device' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.html index bfd091dc57..3270f95a53 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.html @@ -17,7 +17,7 @@ -->
    -
    tb.rulenode.relation-parameters
    +
    rule-node-config.relation-parameters
    relation.direction @@ -34,10 +34,10 @@
    -
    - {{ 'tb.rulenode.delete-relation-with-specific-entity' | translate }} + {{ 'rule-node-config.delete-relation-with-specific-entity' | translate }}
    @@ -56,7 +56,7 @@
    + [hintText]="'rule-node-config.kv-map-single-pattern-hint'">
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts index a59793f767..34337f95ad 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-relation-config.component.ts @@ -31,20 +31,20 @@ export class DeleteRelationConfigComponent extends RuleNodeConfigurationComponen directionTypeTranslations = new Map( [ - [EntitySearchDirection.FROM, 'tb.rulenode.del-relation-direction-from'], - [EntitySearchDirection.TO, 'tb.rulenode.del-relation-direction-to'], + [EntitySearchDirection.FROM, 'rule-node-config.del-relation-direction-from'], + [EntitySearchDirection.TO, 'rule-node-config.del-relation-direction-to'], ] ); entityTypeNamePatternTranslation = new Map( [ - [EntityType.DEVICE, 'tb.rulenode.device-name-pattern'], - [EntityType.ASSET, 'tb.rulenode.asset-name-pattern'], - [EntityType.ENTITY_VIEW, 'tb.rulenode.entity-view-name-pattern'], - [EntityType.CUSTOMER, 'tb.rulenode.customer-title-pattern'], - [EntityType.USER, 'tb.rulenode.user-name-pattern'], - [EntityType.DASHBOARD, 'tb.rulenode.dashboard-name-pattern'], - [EntityType.EDGE, 'tb.rulenode.edge-name-pattern'] + [EntityType.DEVICE, 'rule-node-config.device-name-pattern'], + [EntityType.ASSET, 'rule-node-config.asset-name-pattern'], + [EntityType.ENTITY_VIEW, 'rule-node-config.entity-view-name-pattern'], + [EntityType.CUSTOMER, 'rule-node-config.customer-title-pattern'], + [EntityType.USER, 'rule-node-config.user-name-pattern'], + [EntityType.DASHBOARD, 'rule-node-config.dashboard-name-pattern'], + [EntityType.EDGE, 'rule-node-config.edge-name-pattern'] ] ); diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.html index bb897c6a2d..74594f1400 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/device-profile-config.component.html @@ -16,17 +16,17 @@ -->
    -
    tb.rulenode.device-profile-node-hint
    -
    rule-node-config.device-profile-node-hint
    +
    - {{ 'tb.rulenode.persist-alarm-rules' | translate }} + {{ 'rule-node-config.persist-alarm-rules' | translate }}
    -
    - {{ 'tb.rulenode.fetch-alarm-rules' | translate }} + {{ 'rule-node-config.fetch-alarm-rules' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.html index cae70173ff..812c5e9aed 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/device-state-config.component.html @@ -17,7 +17,7 @@ -->
    - {{ 'tb.rulenode.select-device-connectivity-event' | translate }} + {{ 'rule-node-config.select-device-connectivity-event' | translate }} {{ messageTypeNames.get(eventOption) }} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.html index a3ef3821bd..cdddbf60da 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/generator-config.component.html @@ -17,33 +17,33 @@ -->
    -
    tb.rulenode.generation-parameters
    +
    rule-node-config.generation-parameters
    - tb.rulenode.message-count + rule-node-config.message-count - {{ 'tb.rulenode.message-count-required' | translate }} + {{ 'rule-node-config.message-count-required' | translate }} - {{ 'tb.rulenode.min-message-count-message' | translate }} + {{ 'rule-node-config.min-message-count-message' | translate }} - tb.rulenode.generation-frequency-seconds + rule-node-config.generation-frequency-seconds - {{ 'tb.rulenode.generation-frequency-required' | translate }} + {{ 'rule-node-config.generation-frequency-required' | translate }} - {{ 'tb.rulenode.min-generation-frequency-message' | translate }} + {{ 'rule-node-config.min-generation-frequency-message' | translate }}
    -
    tb.rulenode.originator
    +
    rule-node-config.originator
    - tb.rulenode.generator-function + rule-node-config.generator-function - {{ 'tb.rulenode.script-lang-tbel' | translate }} + {{ 'rule-node-config.script-lang-tbel' | translate }} - {{ 'tb.rulenode.script-lang-js' | translate }} + {{ 'rule-node-config.script-lang-js' | translate }}
    tb.rulenode.no-arguments-prompt + class="tb-prompt flex items-center justify-center">rule-node-config.no-arguments-prompt
    -
    @@ -55,12 +55,12 @@ help + matTooltip="{{ 'rule-node-config.chip-help' | translate: { inputName: 'rule-node-config.device-profile' | translate } }}">help
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.html index b10c9f16b8..238fdce6af 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/example-hint.component.html @@ -24,6 +24,6 @@ tb-help-popup-placement="right" trigger-style="letter-spacing:0.25px; font-size:12px" [tb-help-popup-style]="{maxWidth: '820px'}" - trigger-text="{{ 'tb.key-val.see-examples' | translate }}"> + trigger-text="{{ 'rule-node-config.key-val.see-examples' | translate }}">
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html index 761b9c9491..6678008fd0 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.html @@ -44,7 +44,7 @@ type="button" (click)="removeKeyVal($index)" [disabled]="isLoading$ | async" - matTooltip="{{ 'tb.key-val.remove-entry' | translate }}" + matTooltip="{{ 'rule-node-config.key-val.remove-entry' | translate }}" matTooltipPosition="above"> close @@ -53,7 +53,7 @@
    - tb.rulenode.map-fields-required + rule-node-config.map-fields-required
    - {{ 'tb.key-val.unique-key-value-pair-error' | translate: + {{ 'rule-node-config.key-val.unique-key-value-pair-error' | translate: { valText: valText, keyText: keyText @@ -54,7 +54,7 @@ mat-icon-button (click)="removeKeyVal($index)" [disabled]="disabled" - matTooltip="{{ 'tb.key-val.remove-mapping-entry' | translate }}" + matTooltip="{{ 'rule-node-config.key-val.remove-mapping-entry' | translate }}" matTooltipPosition="above"> delete @@ -65,7 +65,7 @@
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.html index 6a2bf514ad..eb122fe028 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.html @@ -16,7 +16,7 @@ --> - tb.rulenode.functions-field-input + rule-node-config.functions-field-input - tb.rulenode.no-option-found + rule-node-config.no-option-found diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.html index df52912735..174933847e 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.html @@ -47,25 +47,25 @@
    - tb.rulenode.no-message-types-found + rule-node-config.no-message-types-found
    - {{ 'tb.rulenode.no-message-type-matching' | translate : + {{ 'rule-node-config.no-message-type-matching' | translate : {messageType: truncate.transform(searchText, true, 6, '...')} }} - tb.rulenode.create-new-message-type + rule-node-config.create-new-message-type
    help + matTooltip="{{ 'rule-node-config.chip-help' | translate: { inputName: 'rule-node-config.message-type' | translate } }}">help - {{ 'tb.rulenode.select-message-types-required' | translate }} + {{ 'rule-node-config.select-message-types-required' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts index 278819cb80..686c6150aa 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts @@ -56,7 +56,7 @@ export class MessageTypesConfigComponent extends PageComponent implements Contro label: string; @Input() - placeholder = 'tb.rulenode.add-message-type'; + placeholder = 'rule-node-config.add-message-type'; @Input() disabled: boolean; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.html index 832c633d5d..83e2547286 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.html @@ -17,7 +17,7 @@ -->
    - {{'tb.rulenode.output-message-type' | translate}} + {{'rule-node-config.output-message-type' | translate}} {{msgType.name}} @@ -25,7 +25,7 @@ - {{'tb.rulenode.message-type-value' | translate}} + {{'rule-node-config.message-type-value' | translate}} - {{ 'tb.rulenode.message-type-value-required' | translate }} + {{ 'rule-node-config.message-type-value-required' | translate }} - {{ 'tb.rulenode.message-type-value-max-length' | translate }} + {{ 'rule-node-config.message-type-value-max-length' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.html index d60e993e88..6fb7a86005 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.html @@ -29,12 +29,12 @@ - tb.rulenode.max-relation-level + rule-node-config.max-relation-level
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.html index 748076957d..01afac76b6 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.html @@ -16,35 +16,35 @@ -->
    -
    tb.rulenode.relations-query
    +
    rule-node-config.relations-query
    relation.direction - {{ directionTypeTranslations.get(type) | translate }} tb.rulenode.relations-query-config-direction-suffix + {{ directionTypeTranslations.get(type) | translate }} rule-node-config.relations-query-config-direction-suffix - tb.rulenode.max-relation-level + rule-node-config.max-relation-level - {{ 'tb.rulenode.max-relation-level-error' | translate }} + {{ 'rule-node-config.max-relation-level-error' | translate }} - {{ 'tb.rulenode.max-relation-level-invalid' | translate }} + {{ 'rule-node-config.max-relation-level-invalid' | translate }}
    -
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html index 06d63535e9..08de169272 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.html @@ -16,38 +16,38 @@ -->
    - + [placeholder]="'rule-node-config.add-attribute-key' | translate" + [label]="'rule-node-config.client-attributes' | translate" formControlName="clientAttributeNames"> + [placeholder]="'rule-node-config.add-attribute-key' | translate" + [label]="'rule-node-config.shared-attributes' | translate" formControlName="sharedAttributeNames"> + [placeholder]="'rule-node-config.add-attribute-key' | translate" + [label]="'rule-node-config.server-attributes' | translate" formControlName="serverAttributeNames"> + [placeholder]="'rule-node-config.add-telemetry-key' | translate" + [label]="'rule-node-config.latest-telemetry' | translate" formControlName="latestTsKeyNames"> -
    - {{ 'tb.rulenode.fetch-latest-telemetry-with-timestamp' | translate }} + {{ 'rule-node-config.fetch-latest-telemetry-with-timestamp' | translate }}
    @@ -55,5 +55,5 @@ help + matTooltip="{{ 'rule-node-config.chip-help' | translate: { inputName: 'rule-node-config.field-name' | translate } }}">help diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.html index 6deeb54f67..21ed014ec3 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.html @@ -19,7 +19,7 @@
    {{ labelText }}
    - tb.rulenode.map-fields-required + rule-node-config.map-fields-required
    {{ requiredText }} @@ -51,7 +51,7 @@ mat-icon-button (click)="removeKeyVal($index)" [disabled]="isLoading$ | async" - matTooltip="{{ 'tb.key-val.remove-mapping-entry' | translate }}" + matTooltip="{{ 'rule-node-config.key-val.remove-mapping-entry' | translate }}" matTooltipPosition="above"> delete @@ -63,7 +63,7 @@
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.html index b727008bb3..6d9924f4f8 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/calculate-delta-config.component.html @@ -18,74 +18,74 @@
    - {{ 'tb.rulenode.input-value-key' | translate }} + {{ 'rule-node-config.input-value-key' | translate }} - {{ 'tb.rulenode.input-value-key-required' | translate }} + {{ 'rule-node-config.input-value-key-required' | translate }} - {{ 'tb.rulenode.output-value-key' | translate }} + {{ 'rule-node-config.output-value-key' | translate }} - {{ 'tb.rulenode.output-value-key-required' | translate }} + {{ 'rule-node-config.output-value-key-required' | translate }}
    - {{ 'tb.rulenode.number-of-digits-after-floating-point' | translate }} + {{ 'rule-node-config.number-of-digits-after-floating-point' | translate }} - {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }} + {{ 'rule-node-config.number-of-digits-after-floating-point-range' | translate }} - {{ 'tb.rulenode.number-of-digits-after-floating-point-range' | translate }} + {{ 'rule-node-config.number-of-digits-after-floating-point-range' | translate }}
    -
    - {{ 'tb.rulenode.failure-if-delta-negative' | translate }} + {{ 'rule-node-config.failure-if-delta-negative' | translate }}
    -
    - {{ 'tb.rulenode.use-caching' | translate }} + {{ 'rule-node-config.use-caching' | translate }}
    -
    - {{ 'tb.rulenode.add-time-difference-between-readings' | translate: + {{ 'rule-node-config.add-time-difference-between-readings' | translate: { inputValueKey: calculateDeltaConfigForm.get('inputValueKey').valid ? - calculateDeltaConfigForm.get('inputValueKey').value : 'tb.rulenode.input-value-key' | translate } }} + calculateDeltaConfigForm.get('inputValueKey').value : 'rule-node-config.input-value-key' | translate } }}
    - {{ 'tb.rulenode.period-value-key' | translate }} + {{ 'rule-node-config.period-value-key' | translate }} - {{ 'tb.rulenode.period-value-key-required' | translate }} + {{ 'rule-node-config.period-value-key-required' | translate }}
    -
    - {{ 'tb.rulenode.exclude-zero-deltas' | translate }} + {{ 'rule-node-config.exclude-zero-deltas' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.html index 182d580eec..20377be84b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/customer-attributes-config.component.html @@ -16,7 +16,7 @@ -->
    -
    tb.rulenode.mapping-of-customers
    +
    rule-node-config.mapping-of-customers
    @@ -29,18 +29,18 @@
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.html index c17edb1e92..f2c33cf0b5 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/device-attributes-config.component.html @@ -17,7 +17,7 @@ -->
    -
    tb.rulenode.device-relations-query
    +
    rule-node-config.device-relations-query
    @@ -25,22 +25,22 @@
    -
    tb.rulenode.related-device-attributes
    +
    rule-node-config.related-device-attributes
    - tb.rulenode.at-least-one-field-required + rule-node-config.at-least-one-field-required
    + [labelText]="'rule-node-config.add-selected-attributes-to' | translate">
    -
    - {{ 'tb.rulenode.tell-failure' | translate }} + {{ 'rule-node-config.tell-failure' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.html index 1065aa6a09..07fc97a716 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/entity-details-config.component.html @@ -18,18 +18,18 @@
    + matTooltip="{{ 'rule-node-config.chip-help' | translate: { inputName: 'rule-node-config.detail' | translate } }}"> help
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.html index a76d3341d7..aa210dfcc1 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/fetch-device-credentials-config.component.html @@ -17,7 +17,7 @@ -->
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.html index 9b656096f8..6dafe65457 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/get-telemetry-from-database-config.component.html @@ -16,47 +16,47 @@ -->
    - + [requiredText]="'rule-node-config.timeseries-keys-required' | translate" + [label]="'rule-node-config.timeseries-keys' | translate" formControlName="latestTsKeyNames" + [hint]="'rule-node-config.general-pattern-hint' | translate">
    + trigger-text="{{ 'rule-node-config.key-val.see-examples' | translate }}">
    help + matTooltip="{{ 'rule-node-config.chip-help' | translate: { inputName: 'rule-node-config.timeseries-key' | translate } }}">help
    -
    tb.rulenode.fetch-interval
    -
    rule-node-config.fetch-interval
    +
    - {{ 'tb.rulenode.use-metadata-dynamic-interval' | translate }} + {{ 'rule-node-config.use-metadata-dynamic-interval' | translate }}
    - {{ 'tb.rulenode.interval-start' | translate }} + {{ 'rule-node-config.interval-start' | translate }} - {{ 'tb.rulenode.start-interval-value-required' | translate }} + {{ 'rule-node-config.start-interval-value-required' | translate }} - {{ 'tb.rulenode.time-value-range' | translate }} + {{ 'rule-node-config.time-value-range' | translate }} - {{ 'tb.rulenode.time-value-range' | translate }} + {{ 'rule-node-config.time-value-range' | translate }} - {{ 'tb.rulenode.time-unit' | translate }} + {{ 'rule-node-config.time-unit' | translate }} {{ timeUnitsTranslationMap.get(timeUnit) | translate }} @@ -66,20 +66,20 @@
    - {{ 'tb.rulenode.interval-end' | translate }} + {{ 'rule-node-config.interval-end' | translate }} - {{ 'tb.rulenode.end-interval-value-required' | translate }} + {{ 'rule-node-config.end-interval-value-required' | translate }} - {{ 'tb.rulenode.time-value-range' | translate }} + {{ 'rule-node-config.time-value-range' | translate }} - {{ 'tb.rulenode.time-value-range' | translate }} + {{ 'rule-node-config.time-value-range' | translate }} - {{ 'tb.rulenode.time-unit' | translate }} + {{ 'rule-node-config.time-unit' | translate }} {{ timeUnitsTranslationMap.get(timeUnit) | translate }} @@ -91,7 +91,7 @@ error_outline
    - {{ 'tb.rulenode.fetch-timeseries-from-to' | translate: + {{ 'rule-node-config.fetch-timeseries-from-to' | translate: { startInterval: getTelemetryFromDatabaseConfigForm.get('interval.startInterval').value, endInterval: getTelemetryFromDatabaseConfigForm.get('interval.endInterval').value, @@ -100,7 +100,7 @@ } }} - {{ "tb.rulenode.fetch-timeseries-from-to-invalid" | translate }} + {{ "rule-node-config.fetch-timeseries-from-to-invalid" | translate }}
    @@ -108,29 +108,29 @@
    - {{ 'tb.rulenode.start-interval' | translate }} + {{ 'rule-node-config.start-interval' | translate }} - {{ 'tb.rulenode.start-interval-required' | translate }} + {{ 'rule-node-config.start-interval-required' | translate }} - {{ 'tb.rulenode.end-interval' | translate }} + {{ 'rule-node-config.end-interval' | translate }} - {{ 'tb.rulenode.end-interval-required' | translate }} + {{ 'rule-node-config.end-interval-required' | translate }} -
    -
    tb.rulenode.fetch-strategy
    +
    rule-node-config.fetch-strategy
    @@ -155,7 +155,7 @@
    - {{ "tb.rulenode.order-by-timestamp" | translate }} + {{ "rule-node-config.order-by-timestamp" | translate }} {{ samplingOrdersTranslate.get(order) | translate }} @@ -163,17 +163,17 @@ - {{ "tb.rulenode.limit" | translate }} + {{ "rule-node-config.limit" | translate }} - {{ "tb.rulenode.limit-hint" | translate }} + {{ "rule-node-config.limit-hint" | translate }} - {{ 'tb.rulenode.limit-required' | translate }} + {{ 'rule-node-config.limit-required' | translate }} - {{ 'tb.rulenode.limit-range' | translate }} + {{ 'rule-node-config.limit-range' | translate }} - {{ 'tb.rulenode.limit-range' | translate }} + {{ 'rule-node-config.limit-range' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.html index caf7c63d11..6c767c3664 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-attributes-config.component.html @@ -18,23 +18,23 @@
    -
    tb.rulenode.originator-attributes
    +
    rule-node-config.originator-attributes
    - tb.rulenode.at-least-one-field-required + rule-node-config.at-least-one-field-required
    -
    -
    +
    - {{ 'tb.rulenode.tell-failure' | translate }} + {{ 'rule-node-config.tell-failure' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.html index 6ec066f230..4f5ed6cf13 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/originator-fields-config.component.html @@ -21,21 +21,21 @@ [selectOptions]="originatorFields" targetKeyPrefix="originator" formControlName="dataMapping" - [requiredText]="'tb.rulenode.attr-mapping-required' | translate" - [labelText]="'tb.rulenode.originator-fields-mapping' | translate" - [selectText]="'tb.rulenode.source-field' | translate" - [selectRequiredText]="'tb.rulenode.source-field-required' | translate" - [valText]="'tb.rulenode.target-key' | translate" - [valRequiredText]="'tb.rulenode.target-key-required' | translate" - [hintText]="'tb.rulenode.originator-fields-sv-map-hint' | translate" + [requiredText]="'rule-node-config.attr-mapping-required' | translate" + [labelText]="'rule-node-config.originator-fields-mapping' | translate" + [selectText]="'rule-node-config.source-field' | translate" + [selectRequiredText]="'rule-node-config.source-field-required' | translate" + [valText]="'rule-node-config.target-key' | translate" + [valRequiredText]="'rule-node-config.target-key-required' | translate" + [hintText]="'rule-node-config.originator-fields-sv-map-hint' | translate" popupHelpLink="rulenode/originator_fields_node_fields_templatization"> - -
    +
    - {{ 'tb.rulenode.skip-empty-fields' | translate }} + {{ 'rule-node-config.skip-empty-fields' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.html index a7d9f74e1d..677ffb52eb 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/related-attributes-config.component.html @@ -21,7 +21,7 @@ formControlName="relationsQuery">
    -
    tb.rulenode.data-to-fetch
    +
    rule-node-config.data-to-fetch
    {{ data.name }} @@ -31,28 +31,28 @@ [hidden]="relatedAttributesConfigForm.get('dataToFetch').value === DataToFetch.FIELDS" required formControlName="kvMap" - [requiredText]="'tb.rulenode.attr-mapping-required' | translate" - [labelText]="selectTranslation('tb.rulenode.latest-telemetry-mapping','tb.rulenode.attributes-mapping') | translate" - [keyText]="selectTranslation('tb.rulenode.source-telemetry','tb.rulenode.source-attribute') | translate" - [keyRequiredText]="selectTranslation('tb.rulenode.source-telemetry-required','tb.rulenode.source-attribute-required') | translate" - [valText]="'tb.rulenode.target-key' | translate" - [valRequiredText]="'tb.rulenode.target-key-required' | translate" - [hintText]="'tb.rulenode.kv-map-pattern-hint'" + [requiredText]="'rule-node-config.attr-mapping-required' | translate" + [labelText]="selectTranslation('rule-node-config.latest-telemetry-mapping','rule-node-config.attributes-mapping') | translate" + [keyText]="selectTranslation('rule-node-config.source-telemetry','rule-node-config.source-attribute') | translate" + [keyRequiredText]="selectTranslation('rule-node-config.source-telemetry-required','rule-node-config.source-attribute-required') | translate" + [valText]="'rule-node-config.target-key' | translate" + [valRequiredText]="'rule-node-config.target-key-required' | translate" + [hintText]="'rule-node-config.kv-map-pattern-hint'" popupHelpLink="rulenode/related_entity_data_node_fields_templatization">
    -
    tb.rulenode.mapping-of-tenant
    +
    rule-node-config.mapping-of-tenant
    @@ -29,17 +29,17 @@ + ('rule-node-config.add-mapped-latest-telemetry-to' | translate) : ('rule-node-config.add-mapped-attribute-to' | translate)">
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.html index 44fe7d2ebd..59dcb40fec 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.html @@ -17,45 +17,45 @@ -->
    - tb.rulenode.topic + rule-node-config.topic - {{ 'tb.rulenode.topic-required' | translate }} + {{ 'rule-node-config.topic-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint - tb.rulenode.hostname + rule-node-config.hostname - {{ 'tb.rulenode.hostname-required' | translate }} + {{ 'rule-node-config.hostname-required' | translate }} - tb.rulenode.device-id + rule-node-config.device-id - {{ 'tb.rulenode.device-id-required' | translate }} + {{ 'rule-node-config.device-id-required' | translate }} - tb.rulenode.credentials + rule-node-config.credentials {{ azureIotHubCredentialsTypeTranslationsMap.get(azureIotHubConfigForm.get('credentials.type').value) | translate }}
    - tb.rulenode.credentials-type + rule-node-config.credentials-type {{ azureIotHubCredentialsTypeTranslationsMap.get(credentialsType) | translate }} - {{ 'tb.rulenode.credentials-type-required' | translate }} + {{ 'rule-node-config.credentials-type-required' | translate }}
    @@ -63,20 +63,20 @@ - tb.rulenode.sas-key + rule-node-config.sas-key - {{ 'tb.rulenode.sas-key-required' | translate }} + {{ 'rule-node-config.sas-key-required' | translate }} + label="{{'rule-node-config.azure-ca-cert' | translate}}" + noFileText="rule-node-config.no-file" + dropLabel="{{'rule-node-config.drop-file' | translate}}"> @@ -84,9 +84,9 @@ inputId="caCertSelect" [existingFileName]="azureIotHubConfigForm.get('credentials.caCertFileName').value" (fileNameChanged)="azureIotHubConfigForm.get('credentials.caCertFileName').setValue($event)" - label="{{'tb.rulenode.azure-ca-cert' | translate}}" - noFileText="tb.rulenode.no-file" - dropLabel="{{'tb.rulenode.drop-file' | translate}}"> + label="{{'rule-node-config.azure-ca-cert' | translate}}" + noFileText="rule-node-config.no-file" + dropLabel="{{'rule-node-config.drop-file' | translate}}"> + label="{{'rule-node-config.cert' | translate}}" + noFileText="rule-node-config.no-file" + dropLabel="{{'rule-node-config.drop-file' | translate}}"> + label="{{'rule-node-config.private-key' | translate}}" + noFileText="rule-node-config.no-file" + dropLabel="{{'rule-node-config.drop-file' | translate}}"> - tb.rulenode.private-key-password + rule-node-config.private-key-password diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.html index 6bb1438a00..f23bbd353c 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/kafka-config.component.html @@ -17,56 +17,56 @@ -->
    - tb.rulenode.topic-pattern + rule-node-config.topic-pattern - {{ 'tb.rulenode.topic-pattern-required' | translate }} + {{ 'rule-node-config.topic-pattern-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint - tb.rulenode.key-pattern + rule-node-config.key-pattern - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint -
    tb.rulenode.key-pattern-hint
    +
    rule-node-config.key-pattern-hint
    - tb.rulenode.bootstrap-servers + rule-node-config.bootstrap-servers - {{ 'tb.rulenode.bootstrap-servers-required' | translate }} + {{ 'rule-node-config.bootstrap-servers-required' | translate }} - tb.rulenode.retries + rule-node-config.retries - {{ 'tb.rulenode.min-retries-message' | translate }} + {{ 'rule-node-config.min-retries-message' | translate }} - tb.rulenode.batch-size-bytes + rule-node-config.batch-size-bytes - {{ 'tb.rulenode.min-batch-size-bytes-message' | translate }} + {{ 'rule-node-config.min-batch-size-bytes-message' | translate }} - tb.rulenode.linger-ms + rule-node-config.linger-ms - {{ 'tb.rulenode.min-linger-ms-message' | translate }} + {{ 'rule-node-config.min-linger-ms-message' | translate }} - tb.rulenode.buffer-memory-bytes + rule-node-config.buffer-memory-bytes - {{ 'tb.rulenode.min-buffer-memory-bytes-message' | translate }} + {{ 'rule-node-config.min-buffer-memory-bytes-message' | translate }} - tb.rulenode.acks + rule-node-config.acks {{ ackValue }} @@ -74,34 +74,34 @@ - tb.rulenode.key-serializer + rule-node-config.key-serializer - {{ 'tb.rulenode.key-serializer-required' | translate }} + {{ 'rule-node-config.key-serializer-required' | translate }} - tb.rulenode.value-serializer + rule-node-config.value-serializer - {{ 'tb.rulenode.value-serializer-required' | translate }} + {{ 'rule-node-config.value-serializer-required' | translate }} - + + keyText="rule-node-config.key" + keyRequiredText="rule-node-config.key-required" + valText="rule-node-config.value" + valRequiredText="rule-node-config.value-required"> - {{ 'tb.rulenode.add-metadata-key-values-as-kafka-headers' | translate }} + {{ 'rule-node-config.add-metadata-key-values-as-kafka-headers' | translate }} -
    tb.rulenode.add-metadata-key-values-as-kafka-headers-hint
    +
    rule-node-config.add-metadata-key-values-as-kafka-headers-hint
    - tb.rulenode.charset-encoding + rule-node-config.charset-encoding {{ ToByteStandartCharsetTypeTranslationMap.get(charset) | translate }} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.html index a6907082fc..2ea8fa3957 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/lambda-config.component.html @@ -18,23 +18,23 @@
    -
    tb.rulenode.function-configuration
    +
    rule-node-config.function-configuration
    -
    - {{'tb.rulenode.function-name' | translate}} + {{'rule-node-config.function-name' | translate}} - {{'tb.rulenode.function-name-required' | translate}} + {{'rule-node-config.function-name-required' | translate}} - {{'tb.rulenode.qualifier' | translate}} + {{'rule-node-config.qualifier' | translate}} - tb.rulenode.qualifier-hint + rule-node-config.qualifier-hint
    @@ -42,28 +42,28 @@
    - tb.rulenode.aws-credentials + rule-node-config.aws-credentials
    - tb.rulenode.aws-access-key-id + rule-node-config.aws-access-key-id - {{ 'tb.rulenode.aws-access-key-id-required' | translate }} + {{ 'rule-node-config.aws-access-key-id-required' | translate }} - tb.rulenode.aws-secret-access-key + rule-node-config.aws-secret-access-key - {{ 'tb.rulenode.aws-secret-access-key-required' | translate }} + {{ 'rule-node-config.aws-secret-access-key-required' | translate }} - tb.rulenode.aws-region + rule-node-config.aws-region - {{ 'tb.rulenode.aws-region-required' | translate }} + {{ 'rule-node-config.aws-region-required' | translate }}
    @@ -72,41 +72,41 @@
    - tb.rulenode.advanced-settings + rule-node-config.advanced-settings
    - tb.rulenode.connection-timeout + rule-node-config.connection-timeout - {{ 'tb.rulenode.connection-timeout-required' | translate }} + {{ 'rule-node-config.connection-timeout-required' | translate }} - {{ 'tb.rulenode.connection-timeout-min' | translate }} + {{ 'rule-node-config.connection-timeout-min' | translate }} help + matTooltip="{{ 'rule-node-config.connection-timeout-hint' | translate }}">help - tb.rulenode.request-timeout + rule-node-config.request-timeout - {{ 'tb.rulenode.request-timeout-required' | translate }} + {{ 'rule-node-config.request-timeout-required' | translate }} - {{ 'tb.rulenode.request-timeout-min' | translate }} + {{ 'rule-node-config.request-timeout-min' | translate }} help + matTooltip="{{ 'rule-node-config.request-timeout-hint' | translate }}">help
    -
    - {{ 'tb.rulenode.tell-failure-aws-lambda' | translate }} + {{ 'rule-node-config.tell-failure-aws-lambda' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html index 989a8829b7..a57da12587 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html @@ -17,69 +17,69 @@ -->
    - tb.rulenode.topic-pattern + rule-node-config.topic-pattern - {{ 'tb.rulenode.topic-pattern-required' | translate }} + {{ 'rule-node-config.topic-pattern-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint
    - tb.rulenode.host + rule-node-config.host - {{ 'tb.rulenode.host-required' | translate }} + {{ 'rule-node-config.host-required' | translate }} - tb.rulenode.port + rule-node-config.port - {{ 'tb.rulenode.port-required' | translate }} + {{ 'rule-node-config.port-required' | translate }} - {{ 'tb.rulenode.port-range' | translate }} + {{ 'rule-node-config.port-range' | translate }} - {{ 'tb.rulenode.port-range' | translate }} + {{ 'rule-node-config.port-range' | translate }} - tb.rulenode.connect-timeout + rule-node-config.connect-timeout - {{ 'tb.rulenode.connect-timeout-required' | translate }} + {{ 'rule-node-config.connect-timeout-required' | translate }} - {{ 'tb.rulenode.connect-timeout-range' | translate }} + {{ 'rule-node-config.connect-timeout-range' | translate }} - {{ 'tb.rulenode.connect-timeout-range' | translate }} + {{ 'rule-node-config.connect-timeout-range' | translate }}
    - tb.rulenode.client-id + rule-node-config.client-id - {{'tb.rulenode.client-id-hint' | translate}} + {{'rule-node-config.client-id-hint' | translate}} - {{ 'tb.rulenode.append-client-id-suffix' | translate }} + {{ 'rule-node-config.append-client-id-suffix' | translate }} -
    {{ "tb.rulenode.client-id-suffix-hint" | translate }}
    +
    {{ "rule-node-config.client-id-suffix-hint" | translate }}
    - {{ 'tb.rulenode.parse-to-plain-text' | translate }} + {{ 'rule-node-config.parse-to-plain-text' | translate }} -
    {{ "tb.rulenode.parse-to-plain-text-hint" | translate }}
    +
    {{ "rule-node-config.parse-to-plain-text-hint" | translate }}
    - {{ 'tb.rulenode.clean-session' | translate }} + {{ 'rule-node-config.clean-session' | translate }} - {{ "tb.rulenode.retained-message" | translate }} + {{ "rule-node-config.retained-message" | translate }} - {{ 'tb.rulenode.enable-ssl' | translate }} + {{ 'rule-node-config.enable-ssl' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.html index eb5c700400..b3d303765a 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/pubsub-config.component.html @@ -17,17 +17,17 @@ -->
    - tb.rulenode.gcp-project-id + rule-node-config.gcp-project-id - {{ 'tb.rulenode.gcp-project-id-required' | translate }} + {{ 'rule-node-config.gcp-project-id-required' | translate }} - tb.rulenode.pubsub-topic-name + rule-node-config.pubsub-topic-name - {{ 'tb.rulenode.pubsub-topic-name-required' | translate }} + {{ 'rule-node-config.pubsub-topic-name-required' | translate }} + label="{{'rule-node-config.gcp-service-account-key' | translate}}" + noFileText="rule-node-config.no-file" + dropLabel="{{'rule-node-config.drop-file' | translate}}"> - -
    + +
    + keyText="rule-node-config.name" + keyRequiredText="rule-node-config.name-required" + valText="rule-node-config.value" + valRequiredText="rule-node-config.value-required">
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.html index 0ef6b40877..c04b0be902 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rabbit-mq-config.component.html @@ -17,15 +17,15 @@ -->
    - tb.rulenode.exchange-name-pattern + rule-node-config.exchange-name-pattern - tb.rulenode.routing-key-pattern + rule-node-config.routing-key-pattern - tb.rulenode.message-properties + rule-node-config.message-properties {{ property }} @@ -34,63 +34,63 @@
    - tb.rulenode.host + rule-node-config.host - {{ 'tb.rulenode.host-required' | translate }} + {{ 'rule-node-config.host-required' | translate }} - tb.rulenode.port + rule-node-config.port - {{ 'tb.rulenode.port-required' | translate }} + {{ 'rule-node-config.port-required' | translate }} - {{ 'tb.rulenode.port-range' | translate }} + {{ 'rule-node-config.port-range' | translate }} - {{ 'tb.rulenode.port-range' | translate }} + {{ 'rule-node-config.port-range' | translate }}
    - tb.rulenode.virtual-host + rule-node-config.virtual-host - tb.rulenode.username + rule-node-config.username - tb.rulenode.password + rule-node-config.password - {{ 'tb.rulenode.automatic-recovery' | translate }} + {{ 'rule-node-config.automatic-recovery' | translate }} - tb.rulenode.connection-timeout-ms + rule-node-config.connection-timeout-ms - {{ 'tb.rulenode.min-connection-timeout-ms-message' | translate }} + {{ 'rule-node-config.min-connection-timeout-ms-message' | translate }} - tb.rulenode.handshake-timeout-ms + rule-node-config.handshake-timeout-ms - {{ 'tb.rulenode.min-handshake-timeout-ms-message' | translate }} + {{ 'rule-node-config.min-handshake-timeout-ms-message' | translate }} - + + keyText="rule-node-config.key" + keyRequiredText="rule-node-config.key-required" + valText="rule-node-config.value" + valRequiredText="rule-node-config.value-required">
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html index 5dfca5144a..0bae38471f 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/rest-api-call-config.component.html @@ -17,15 +17,15 @@ -->
    - tb.rulenode.endpoint-url-pattern + rule-node-config.endpoint-url-pattern - {{ 'tb.rulenode.endpoint-url-pattern-required' | translate }} + {{ 'rule-node-config.endpoint-url-pattern-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint - tb.rulenode.request-method + rule-node-config.request-method {{ requestType }} @@ -33,26 +33,26 @@ - {{ 'tb.rulenode.enable-proxy' | translate }} + {{ 'rule-node-config.enable-proxy' | translate }} - {{ 'tb.rulenode.use-simple-client-http-factory' | translate }} + {{ 'rule-node-config.use-simple-client-http-factory' | translate }} - {{ 'tb.rulenode.parse-to-plain-text' | translate }} + {{ 'rule-node-config.parse-to-plain-text' | translate }} -
    tb.rulenode.parse-to-plain-text-hint
    +
    rule-node-config.parse-to-plain-text-hint
    - {{ 'tb.rulenode.ignore-request-body' | translate }} + {{ 'rule-node-config.ignore-request-body' | translate }}
    - {{ 'tb.rulenode.use-system-proxy-properties' | translate }} + {{ 'rule-node-config.use-system-proxy-properties' | translate }}
    - tb.rulenode.proxy-scheme + rule-node-config.proxy-scheme {{ proxyScheme }} @@ -60,71 +60,71 @@ - tb.rulenode.proxy-host + rule-node-config.proxy-host - {{ 'tb.rulenode.proxy-host-required' | translate }} + {{ 'rule-node-config.proxy-host-required' | translate }} - tb.rulenode.proxy-port + rule-node-config.proxy-port - {{ 'tb.rulenode.proxy-port-required' | translate }} + {{ 'rule-node-config.proxy-port-required' | translate }} - {{ 'tb.rulenode.proxy-port-range' | translate }} + {{ 'rule-node-config.proxy-port-range' | translate }}
    - tb.rulenode.proxy-user + rule-node-config.proxy-user - tb.rulenode.proxy-password + rule-node-config.proxy-password
    - tb.rulenode.read-timeout + rule-node-config.read-timeout - tb.rulenode.read-timeout-hint + rule-node-config.read-timeout-hint - {{ 'tb.rulenode.int-range' | translate }} + {{ 'rule-node-config.int-range' | translate }} - tb.rulenode.max-parallel-requests-count + rule-node-config.max-parallel-requests-count - tb.rulenode.max-parallel-requests-count-hint + rule-node-config.max-parallel-requests-count-hint - {{ 'tb.rulenode.int-range' | translate }} + {{ 'rule-node-config.int-range' | translate }} - tb.rulenode.max-response-size + rule-node-config.max-response-size - tb.rulenode.max-response-size-hint + rule-node-config.max-response-size-hint - {{ 'tb.rulenode.memory-buffer-size-range' | translate: { max: MemoryBufferSizeInKbLimit } }} + {{ 'rule-node-config.memory-buffer-size-range' | translate: { max: MemoryBufferSizeInKbLimit } }} - -
    + +
    + keyText="rule-node-config.header" + keyRequiredText="rule-node-config.header-required" + valText="rule-node-config.value" + valRequiredText="rule-node-config.value-required">
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.html index cbc4ec7a4a..f24c20038b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/send-email-config.component.html @@ -17,11 +17,11 @@ -->
    - {{ 'tb.rulenode.use-system-smtp-settings' | translate }} + {{ 'rule-node-config.use-system-smtp-settings' | translate }}
    - tb.rulenode.smtp-protocol + rule-node-config.smtp-protocol {{ smtpProtocol.toUpperCase() }} @@ -30,41 +30,41 @@
    - tb.rulenode.smtp-host + rule-node-config.smtp-host - {{ 'tb.rulenode.smtp-host-required' | translate }} + {{ 'rule-node-config.smtp-host-required' | translate }} - tb.rulenode.smtp-port + rule-node-config.smtp-port - {{ 'tb.rulenode.smtp-port-required' | translate }} + {{ 'rule-node-config.smtp-port-required' | translate }} - {{ 'tb.rulenode.smtp-port-range' | translate }} + {{ 'rule-node-config.smtp-port-range' | translate }} - {{ 'tb.rulenode.smtp-port-range' | translate }} + {{ 'rule-node-config.smtp-port-range' | translate }}
    - tb.rulenode.timeout-msec + rule-node-config.timeout-msec - {{ 'tb.rulenode.timeout-required' | translate }} + {{ 'rule-node-config.timeout-required' | translate }} - {{ 'tb.rulenode.min-timeout-msec-message' | translate }} + {{ 'rule-node-config.min-timeout-msec-message' | translate }} - {{ 'tb.rulenode.enable-tls' | translate }} + {{ 'rule-node-config.enable-tls' | translate }} - tb.rulenode.tls-version + rule-node-config.tls-version {{ tlsVersion }} @@ -72,44 +72,44 @@ - {{ 'tb.rulenode.enable-proxy' | translate }} + {{ 'rule-node-config.enable-proxy' | translate }}
    - tb.rulenode.proxy-host + rule-node-config.proxy-host - {{ 'tb.rulenode.proxy-host-required' | translate }} + {{ 'rule-node-config.proxy-host-required' | translate }} - tb.rulenode.proxy-port + rule-node-config.proxy-port - {{ 'tb.rulenode.proxy-port-required' | translate }} + {{ 'rule-node-config.proxy-port-required' | translate }} - {{ 'tb.rulenode.proxy-port-range' | translate }} + {{ 'rule-node-config.proxy-port-range' | translate }}
    - tb.rulenode.proxy-user + rule-node-config.proxy-user - tb.rulenode.proxy-password + rule-node-config.proxy-password
    - tb.rulenode.username - + rule-node-config.username + - tb.rulenode.password - + rule-node-config.password +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.html index 12f9208c5d..3b4e63308a 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/send-sms-config.component.html @@ -17,23 +17,23 @@ -->
    - tb.rulenode.numbers-to-template + rule-node-config.numbers-to-template - {{ 'tb.rulenode.numbers-to-template-required' | translate }} + {{ 'rule-node-config.numbers-to-template-required' | translate }} - + - tb.rulenode.sms-message-template + rule-node-config.sms-message-template - {{ 'tb.rulenode.sms-message-template-required' | translate }} + {{ 'rule-node-config.sms-message-template-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint - {{ 'tb.rulenode.use-system-sms-settings' | translate }} + {{ 'rule-node-config.use-system-sms-settings' | translate }}
    - tb.rulenode.message-template + rule-node-config.message-template - {{ 'tb.rulenode.message-template-required' | translate }} + {{ 'rule-node-config.message-template-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint - {{ 'tb.rulenode.use-system-slack-settings' | translate }} + {{ 'rule-node-config.use-system-slack-settings' | translate }} - tb.rulenode.slack-api-token + rule-node-config.slack-api-token - {{ 'tb.rulenode.slack-api-token-required' | translate }} + {{ 'rule-node-config.slack-api-token-required' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.html index f4e4aa738d..a5be9017a3 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/sns-config.component.html @@ -17,32 +17,32 @@ -->
    - tb.rulenode.topic-arn-pattern + rule-node-config.topic-arn-pattern - {{ 'tb.rulenode.topic-arn-pattern-required' | translate }} + {{ 'rule-node-config.topic-arn-pattern-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint - tb.rulenode.aws-access-key-id + rule-node-config.aws-access-key-id - {{ 'tb.rulenode.aws-access-key-id-required' | translate }} + {{ 'rule-node-config.aws-access-key-id-required' | translate }} - tb.rulenode.aws-secret-access-key + rule-node-config.aws-secret-access-key - {{ 'tb.rulenode.aws-secret-access-key-required' | translate }} + {{ 'rule-node-config.aws-secret-access-key-required' | translate }} - tb.rulenode.aws-region + rule-node-config.aws-region - {{ 'tb.rulenode.aws-region-required' | translate }} + {{ 'rule-node-config.aws-region-required' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.html index a7272e6d66..2956cc4ab0 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/sqs-config.component.html @@ -17,7 +17,7 @@ -->
    - tb.rulenode.queue-type + rule-node-config.queue-type {{ sqsQueueTypeTranslationsMap.get(type) | translate }} @@ -25,52 +25,52 @@ - tb.rulenode.queue-url-pattern + rule-node-config.queue-url-pattern - {{ 'tb.rulenode.queue-url-pattern-required' | translate }} + {{ 'rule-node-config.queue-url-pattern-required' | translate }} - tb.rulenode.general-pattern-hint + rule-node-config.general-pattern-hint - tb.rulenode.delay-seconds + rule-node-config.delay-seconds - {{ 'tb.rulenode.min-delay-seconds-message' | translate }} + {{ 'rule-node-config.min-delay-seconds-message' | translate }} - {{ 'tb.rulenode.max-delay-seconds-message' | translate }} + {{ 'rule-node-config.max-delay-seconds-message' | translate }} - -
    + +
    + keyText="rule-node-config.name" + keyRequiredText="rule-node-config.name-required" + valText="rule-node-config.value" + valRequiredText="rule-node-config.value-required"> - tb.rulenode.aws-access-key-id + rule-node-config.aws-access-key-id - {{ 'tb.rulenode.aws-access-key-id-required' | translate }} + {{ 'rule-node-config.aws-access-key-id-required' | translate }} - tb.rulenode.aws-secret-access-key + rule-node-config.aws-secret-access-key - {{ 'tb.rulenode.aws-secret-access-key-required' | translate }} + {{ 'rule-node-config.aws-secret-access-key-required' | translate }} - tb.rulenode.aws-region + rule-node-config.aws-region - {{ 'tb.rulenode.aws-region-required' | translate }} + {{ 'rule-node-config.aws-region-required' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.html index 329b876e1e..b8f0faf15f 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-alarm-status.component.html @@ -17,9 +17,9 @@ -->
    -
    tb.rulenode.alarm-status
    +
    rule-node-config.alarm-status
    - tb.rulenode.alarm-required + rule-node-config.alarm-required
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.html index 7ded71d798..6566912570 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-message-config.component.html @@ -17,29 +17,29 @@ -->
    -
    tb.rulenode.fields-to-check
    +
    rule-node-config.fields-to-check
    - tb.rulenode.at-least-one-field-required + rule-node-config.at-least-one-field-required
    help + matTooltip="{{ 'rule-node-config.chip-help' | translate: { inputName: 'rule-node-config.field-name' | translate } }}">help help + matTooltip="{{ 'rule-node-config.chip-help' | translate: { inputName: 'rule-node-config.field-name' | translate } }}">help -
    - {{ 'tb.rulenode.check-all-keys' | translate }} + {{ 'rule-node-config.check-all-keys' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.html index 2a4b61792e..b9763b280f 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/check-relation-config.component.html @@ -16,13 +16,13 @@ -->
    -
    tb.rulenode.relation-search-parameters
    +
    rule-node-config.relation-search-parameters
    {{ 'relation.direction' | translate }} - {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} tb.rulenode.relations-query-config-direction-suffix + {{ entitySearchDirectionTranslationsMap.get(direction) | translate }} rule-node-config.relations-query-config-direction-suffix @@ -30,10 +30,10 @@ required formControlName="relationType"> -
    - {{ 'tb.rulenode.check-relation-to-specific-entity' | translate }} + {{ 'rule-node-config.check-relation-to-specific-entity' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.html index 738e834450..ac09e2156a 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/gps-geo-filter-config.component.html @@ -17,32 +17,32 @@ -->
    -
    tb.rulenode.coordinate-field-names
    +
    rule-node-config.coordinate-field-names
    - {{ 'tb.rulenode.latitude-field-name' | translate }} + {{ 'rule-node-config.latitude-field-name' | translate }} - {{ 'tb.rulenode.latitude-field-name-required' | translate }} + {{ 'rule-node-config.latitude-field-name-required' | translate }} - {{ 'tb.rulenode.longitude-field-name' | translate }} + {{ 'rule-node-config.longitude-field-name' | translate }} - {{ 'tb.rulenode.longitude-field-name-required' | translate }} + {{ 'rule-node-config.longitude-field-name-required' | translate }}
    -
    tb.rulenode.coordinate-field-hint
    +
    rule-node-config.coordinate-field-hint
    -
    tb.rulenode.geofence-configuration
    +
    rule-node-config.geofence-configuration
    - {{ 'tb.rulenode.perimeter-type' | translate }} + {{ 'rule-node-config.perimeter-type' | translate }} {{ perimeterTypeTranslationMap.get(type) | translate }} @@ -50,63 +50,63 @@
    - {{ 'tb.rulenode.fetch-perimeter-info-from-metadata' | translate }} + {{ 'rule-node-config.fetch-perimeter-info-from-metadata' | translate }}
    - {{ 'tb.rulenode.perimeter-key-name' | translate }} + {{ 'rule-node-config.perimeter-key-name' | translate }} - {{ 'tb.rulenode.perimeter-key-name-required' | translate }} + {{ 'rule-node-config.perimeter-key-name-required' | translate }} - {{ 'tb.rulenode.perimeter-key-name-hint' | translate }} + {{ 'rule-node-config.perimeter-key-name-hint' | translate }}
    - {{ 'tb.rulenode.circle-center-latitude' | translate }} + {{ 'rule-node-config.circle-center-latitude' | translate }} - {{ 'tb.rulenode.circle-center-latitude-required' | translate }} + {{ 'rule-node-config.circle-center-latitude-required' | translate }} - {{ 'tb.rulenode.circle-center-longitude' | translate }} + {{ 'rule-node-config.circle-center-longitude' | translate }} - {{ 'tb.rulenode.circle-center-longitude-required' | translate }} + {{ 'rule-node-config.circle-center-longitude-required' | translate }}
    - {{ 'tb.rulenode.range' | translate }} + {{ 'rule-node-config.range' | translate }} - {{ 'tb.rulenode.range-required' | translate }} + {{ 'rule-node-config.range-required' | translate }} - {{ 'tb.rulenode.range-units' | translate }} + {{ 'rule-node-config.range-units' | translate }} {{ rangeUnitTranslationMap.get(type) | translate }} - {{ 'tb.rulenode.range-units-required' | translate }} + {{ 'rule-node-config.range-units-required' | translate }}
    @@ -114,11 +114,11 @@ - {{ 'tb.rulenode.polygon-definition' | translate }} + {{ 'rule-node-config.polygon-definition' | translate }} - {{ 'tb.rulenode.polygon-definition-hint' | translate }} + {{ 'rule-node-config.polygon-definition-hint' | translate }} - {{ 'tb.rulenode.polygon-definition-required' | translate }} + {{ 'rule-node-config.polygon-definition-required' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.html index 1b347ca1d1..847ab255f5 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/message-type-config.component.html @@ -18,7 +18,7 @@
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.html index 233106bd8e..1dc3cf34a2 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/originator-type-config.component.html @@ -20,12 +20,12 @@ formControlName="originatorTypes" [allowedEntityTypes]="allowedEntityTypes" [ignoreAuthorityFilter]="true" - [emptyInputPlaceholder]="'tb.rulenode.add-entity-type' | translate" - [filledInputPlaceholder]="'tb.rulenode.add-entity-type' | translate" - [label]="'tb.rulenode.select-entity-types' | translate" + [emptyInputPlaceholder]="'rule-node-config.add-entity-type' | translate" + [filledInputPlaceholder]="'rule-node-config.add-entity-type' | translate" + [label]="'rule-node-config.select-entity-types' | translate" required> help + matTooltip="{{ 'rule-node-config.chip-help' | translate: { inputName: 'rule-node-config.entity-type' | translate } }}">help
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts index 643f66448f..a5e4ffdea6 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/script-config.component.ts @@ -43,7 +43,7 @@ export class ScriptConfigComponent extends RuleNodeConfigurationComponent { readonly hasScript = true; - readonly testScriptLabel = 'tb.rulenode.test-filter-function'; + readonly testScriptLabel = 'rule-node-config.test-filter-function'; constructor(protected store: Store, private fb: UntypedFormBuilder, @@ -104,7 +104,7 @@ export class ScriptConfigComponent extends RuleNodeConfigurationComponent { this.nodeScriptTestService.testNodeScript( script, 'filter', - this.translate.instant('tb.rulenode.filter'), + this.translate.instant('rule-node-config.filter'), 'Filter', ['msg', 'metadata', 'msgType'], this.ruleNodeId, diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts index a77e5d3e29..c444effd08 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/switch-config.component.ts @@ -46,7 +46,7 @@ export class SwitchConfigComponent extends RuleNodeConfigurationComponent { readonly hasScript = true; - readonly testScriptLabel = 'tb.rulenode.test-switch-function'; + readonly testScriptLabel = 'rule-node-config.test-switch-function'; constructor(private fb: UntypedFormBuilder, private nodeScriptTestService: NodeScriptTestService, @@ -106,7 +106,7 @@ export class SwitchConfigComponent extends RuleNodeConfigurationComponent { this.nodeScriptTestService.testNodeScript( script, 'switch', - this.translate.instant('tb.rulenode.switch'), + this.translate.instant('rule-node-config.switch'), 'Switch', ['msg', 'metadata', 'msgType'], this.ruleNodeId, diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.html b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.html index a91b9980d4..6bee899138 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/rule-chain-input.component.html @@ -17,10 +17,10 @@ -->
    -
    - {{ 'tb.rulenode.forward-msg-default-rule-chain' | translate }} + {{ 'rule-node-config.forward-msg-default-rule-chain' | translate }}
    -
    +
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.models.ts b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.models.ts index 6562a732aa..a358bbaf12 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.models.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.models.ts @@ -34,27 +34,27 @@ export interface OriginatorValuesDescriptions { export const originatorSourceTranslations = new Map( [ - [OriginatorSource.CUSTOMER, 'tb.rulenode.originator-customer'], - [OriginatorSource.TENANT, 'tb.rulenode.originator-tenant'], - [OriginatorSource.RELATED, 'tb.rulenode.originator-related'], - [OriginatorSource.ALARM_ORIGINATOR, 'tb.rulenode.originator-alarm-originator'], - [OriginatorSource.ENTITY, 'tb.rulenode.originator-entity'], + [OriginatorSource.CUSTOMER, 'rule-node-config.originator-customer'], + [OriginatorSource.TENANT, 'rule-node-config.originator-tenant'], + [OriginatorSource.RELATED, 'rule-node-config.originator-related'], + [OriginatorSource.ALARM_ORIGINATOR, 'rule-node-config.originator-alarm-originator'], + [OriginatorSource.ENTITY, 'rule-node-config.originator-entity'], ] ); export const originatorSourceDescTranslations = new Map( [ - [OriginatorSource.CUSTOMER, 'tb.rulenode.originator-customer-desc'], - [OriginatorSource.TENANT, 'tb.rulenode.originator-tenant-desc'], - [OriginatorSource.RELATED, 'tb.rulenode.originator-related-entity-desc'], - [OriginatorSource.ALARM_ORIGINATOR, 'tb.rulenode.originator-alarm-originator-desc'], - [OriginatorSource.ENTITY, 'tb.rulenode.originator-entity-by-name-pattern-desc'], + [OriginatorSource.CUSTOMER, 'rule-node-config.originator-customer-desc'], + [OriginatorSource.TENANT, 'rule-node-config.originator-tenant-desc'], + [OriginatorSource.RELATED, 'rule-node-config.originator-related-entity-desc'], + [OriginatorSource.ALARM_ORIGINATOR, 'rule-node-config.originator-alarm-originator-desc'], + [OriginatorSource.ENTITY, 'rule-node-config.originator-entity-by-name-pattern-desc'], ] ); export const allowedOriginatorFields: EntityField[] = [ entityFields.createdTime, entityFields.name, - {value: 'type', name: 'tb.rulenode.profile-name', keyName: 'originatorProfileName'}, + {value: 'type', name: 'rule-node-config.profile-name', keyName: 'originatorProfileName'}, entityFields.firstName, entityFields.lastName, entityFields.email, @@ -67,8 +67,8 @@ export const allowedOriginatorFields: EntityField[] = [ entityFields.zip, entityFields.phone, entityFields.label, - {value: 'id', name: 'tb.rulenode.id', keyName: 'id'}, - {value: 'additionalInfo', name: 'tb.rulenode.additional-info', keyName: 'additionalInfo'} + {value: 'id', name: 'rule-node-config.id', keyName: 'id'}, + {value: 'additionalInfo', name: 'rule-node-config.additional-info', keyName: 'additionalInfo'} ]; export const OriginatorFieldsMappingValues = new Map( @@ -100,8 +100,8 @@ export enum PerimeterType { export const perimeterTypeTranslations = new Map( [ - [PerimeterType.CIRCLE, 'tb.rulenode.perimeter-circle'], - [PerimeterType.POLYGON, 'tb.rulenode.perimeter-polygon'], + [PerimeterType.CIRCLE, 'rule-node-config.perimeter-circle'], + [PerimeterType.POLYGON, 'rule-node-config.perimeter-polygon'], ] ); @@ -115,11 +115,11 @@ export enum TimeUnit { export const timeUnitTranslations = new Map( [ - [TimeUnit.MILLISECONDS, 'tb.rulenode.time-unit-milliseconds'], - [TimeUnit.SECONDS, 'tb.rulenode.time-unit-seconds'], - [TimeUnit.MINUTES, 'tb.rulenode.time-unit-minutes'], - [TimeUnit.HOURS, 'tb.rulenode.time-unit-hours'], - [TimeUnit.DAYS, 'tb.rulenode.time-unit-days'] + [TimeUnit.MILLISECONDS, 'rule-node-config.time-unit-milliseconds'], + [TimeUnit.SECONDS, 'rule-node-config.time-unit-seconds'], + [TimeUnit.MINUTES, 'rule-node-config.time-unit-minutes'], + [TimeUnit.HOURS, 'rule-node-config.time-unit-hours'], + [TimeUnit.DAYS, 'rule-node-config.time-unit-days'] ] ); @@ -133,11 +133,11 @@ export enum RangeUnit { export const rangeUnitTranslations = new Map( [ - [RangeUnit.METER, 'tb.rulenode.range-unit-meter'], - [RangeUnit.KILOMETER, 'tb.rulenode.range-unit-kilometer'], - [RangeUnit.FOOT, 'tb.rulenode.range-unit-foot'], - [RangeUnit.MILE, 'tb.rulenode.range-unit-mile'], - [RangeUnit.NAUTICAL_MILE, 'tb.rulenode.range-unit-nautical-mile'] + [RangeUnit.METER, 'rule-node-config.range-unit-meter'], + [RangeUnit.KILOMETER, 'rule-node-config.range-unit-kilometer'], + [RangeUnit.FOOT, 'rule-node-config.range-unit-foot'], + [RangeUnit.MILE, 'rule-node-config.range-unit-mile'], + [RangeUnit.NAUTICAL_MILE, 'rule-node-config.range-unit-nautical-mile'] ] ); @@ -162,17 +162,17 @@ export interface SvMapOption { export const entityDetailsTranslations = new Map( [ - [EntityDetailsField.ID, 'tb.rulenode.entity-details-id'], - [EntityDetailsField.TITLE, 'tb.rulenode.entity-details-title'], - [EntityDetailsField.COUNTRY, 'tb.rulenode.entity-details-country'], - [EntityDetailsField.STATE, 'tb.rulenode.entity-details-state'], - [EntityDetailsField.CITY, 'tb.rulenode.entity-details-city'], - [EntityDetailsField.ZIP, 'tb.rulenode.entity-details-zip'], - [EntityDetailsField.ADDRESS, 'tb.rulenode.entity-details-address'], - [EntityDetailsField.ADDRESS2, 'tb.rulenode.entity-details-address2'], - [EntityDetailsField.PHONE, 'tb.rulenode.entity-details-phone'], - [EntityDetailsField.EMAIL, 'tb.rulenode.entity-details-email'], - [EntityDetailsField.ADDITIONAL_INFO, 'tb.rulenode.entity-details-additional_info'] + [EntityDetailsField.ID, 'rule-node-config.entity-details-id'], + [EntityDetailsField.TITLE, 'rule-node-config.entity-details-title'], + [EntityDetailsField.COUNTRY, 'rule-node-config.entity-details-country'], + [EntityDetailsField.STATE, 'rule-node-config.entity-details-state'], + [EntityDetailsField.CITY, 'rule-node-config.entity-details-city'], + [EntityDetailsField.ZIP, 'rule-node-config.entity-details-zip'], + [EntityDetailsField.ADDRESS, 'rule-node-config.entity-details-address'], + [EntityDetailsField.ADDRESS2, 'rule-node-config.entity-details-address2'], + [EntityDetailsField.PHONE, 'rule-node-config.entity-details-phone'], + [EntityDetailsField.EMAIL, 'rule-node-config.entity-details-email'], + [EntityDetailsField.ADDITIONAL_INFO, 'rule-node-config.entity-details-additional_info'] ] ); @@ -184,17 +184,17 @@ export enum FetchMode { export const deduplicationStrategiesTranslations = new Map( [ - [FetchMode.FIRST, 'tb.rulenode.first'], - [FetchMode.LAST, 'tb.rulenode.last'], - [FetchMode.ALL, 'tb.rulenode.all'] + [FetchMode.FIRST, 'rule-node-config.first'], + [FetchMode.LAST, 'rule-node-config.last'], + [FetchMode.ALL, 'rule-node-config.all'] ] ); export const deduplicationStrategiesHintTranslations = new Map( [ - [FetchMode.FIRST, 'tb.rulenode.first-mode-hint'], - [FetchMode.LAST, 'tb.rulenode.last-mode-hint'], - [FetchMode.ALL, 'tb.rulenode.all-mode-hint'] + [FetchMode.FIRST, 'rule-node-config.first-mode-hint'], + [FetchMode.LAST, 'rule-node-config.last-mode-hint'], + [FetchMode.ALL, 'rule-node-config.all-mode-hint'] ] ); @@ -211,24 +211,24 @@ export enum DataToFetch { export const dataToFetchTranslations = new Map( [ - [DataToFetch.ATTRIBUTES, 'tb.rulenode.attributes'], - [DataToFetch.LATEST_TELEMETRY, 'tb.rulenode.latest-telemetry'], - [DataToFetch.FIELDS, 'tb.rulenode.fields'] + [DataToFetch.ATTRIBUTES, 'rule-node-config.attributes'], + [DataToFetch.LATEST_TELEMETRY, 'rule-node-config.latest-telemetry'], + [DataToFetch.FIELDS, 'rule-node-config.fields'] ] ); export const msgMetadataLabelTranslations = new Map( [ - [DataToFetch.ATTRIBUTES, 'tb.rulenode.add-mapped-attribute-to'], - [DataToFetch.LATEST_TELEMETRY, 'tb.rulenode.add-mapped-latest-telemetry-to'], - [DataToFetch.FIELDS, 'tb.rulenode.add-mapped-fields-to'] + [DataToFetch.ATTRIBUTES, 'rule-node-config.add-mapped-attribute-to'], + [DataToFetch.LATEST_TELEMETRY, 'rule-node-config.add-mapped-latest-telemetry-to'], + [DataToFetch.FIELDS, 'rule-node-config.add-mapped-fields-to'] ] ); export const samplingOrderTranslations = new Map( [ - [SamplingOrder.ASC, 'tb.rulenode.ascending'], - [SamplingOrder.DESC, 'tb.rulenode.descending'] + [SamplingOrder.ASC, 'rule-node-config.ascending'], + [SamplingOrder.DESC, 'rule-node-config.descending'] ] ); @@ -239,8 +239,8 @@ export enum SqsQueueType { export const sqsQueueTypeTranslations = new Map( [ - [SqsQueueType.STANDARD, 'tb.rulenode.sqs-queue-standard'], - [SqsQueueType.FIFO, 'tb.rulenode.sqs-queue-fifo'], + [SqsQueueType.STANDARD, 'rule-node-config.sqs-queue-standard'], + [SqsQueueType.FIFO, 'rule-node-config.sqs-queue-fifo'], ] ); @@ -249,9 +249,9 @@ export const credentialsTypes: credentialsType[] = ['anonymous', 'basic', 'cert. export const credentialsTypeTranslations = new Map( [ - ['anonymous', 'tb.rulenode.credentials-anonymous'], - ['basic', 'tb.rulenode.credentials-basic'], - ['cert.PEM', 'tb.rulenode.credentials-pem'] + ['anonymous', 'rule-node-config.credentials-anonymous'], + ['basic', 'rule-node-config.credentials-basic'], + ['cert.PEM', 'rule-node-config.credentials-pem'] ] ); @@ -260,8 +260,8 @@ export const azureIotHubCredentialsTypes: AzureIotHubCredentialsType[] = ['sas', export const azureIotHubCredentialsTypeTranslations = new Map( [ - ['sas', 'tb.rulenode.credentials-sas'], - ['cert.PEM', 'tb.rulenode.credentials-pem'] + ['sas', 'rule-node-config.credentials-sas'], + ['cert.PEM', 'rule-node-config.credentials-pem'] ] ); @@ -283,12 +283,12 @@ export const ToByteStandartCharsetTypes = [ export const ToByteStandartCharsetTypeTranslations = 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'], + ['US-ASCII', 'rule-node-config.charset-us-ascii'], + ['ISO-8859-1', 'rule-node-config.charset-iso-8859-1'], + ['UTF-8', 'rule-node-config.charset-utf-8'], + ['UTF-16BE', 'rule-node-config.charset-utf-16be'], + ['UTF-16LE', 'rule-node-config.charset-utf-16le'], + ['UTF-16', 'rule-node-config.charset-utf-16'], ] ); @@ -720,23 +720,23 @@ export enum FetchTo { } export const FetchFromToTranslation = new Map([ - [FetchTo.DATA, 'tb.rulenode.message-to-metadata'], - [FetchTo.METADATA, 'tb.rulenode.metadata-to-message'], + [FetchTo.DATA, 'rule-node-config.message-to-metadata'], + [FetchTo.METADATA, 'rule-node-config.metadata-to-message'], ]); export const FetchFromTranslation = new Map([ - [FetchTo.DATA, 'tb.rulenode.from-message'], - [FetchTo.METADATA, 'tb.rulenode.from-metadata'], + [FetchTo.DATA, 'rule-node-config.from-message'], + [FetchTo.METADATA, 'rule-node-config.from-metadata'], ]); export const FetchToTranslation = new Map([ - [FetchTo.DATA, 'tb.rulenode.message'], - [FetchTo.METADATA, 'tb.rulenode.metadata'], + [FetchTo.DATA, 'rule-node-config.message'], + [FetchTo.METADATA, 'rule-node-config.metadata'], ]); export const FetchToRenameTranslation = new Map([ - [FetchTo.DATA, 'tb.rulenode.message'], - [FetchTo.METADATA, 'tb.rulenode.message-metadata'], + [FetchTo.DATA, 'rule-node-config.message'], + [FetchTo.METADATA, 'rule-node-config.message-metadata'], ]); export interface ArgumentTypeData { @@ -748,36 +748,36 @@ export const ArgumentTypeMap = new Map([ [ ArgumentType.MESSAGE_BODY, { - name: 'tb.rulenode.message-body-type', - description: 'Fetch argument value from incoming message' + name: 'rule-node-config.message-body-type', + description: 'rule-node-config.message-body-type-description' } ], [ ArgumentType.MESSAGE_METADATA, { - name: 'tb.rulenode.message-metadata-type', - description: 'Fetch argument value from incoming message metadata' + name: 'rule-node-config.message-metadata-type', + description: 'rule-node-config.message-metadata-type-description' } ], [ ArgumentType.ATTRIBUTE, { - name: 'tb.rulenode.attribute-type', - description: 'Fetch attribute value from database' + name: 'rule-node-config.attribute-type', + description: 'rule-node-config.attribute-type-description' } ], [ ArgumentType.TIME_SERIES, { - name: 'tb.rulenode.time-series-type', - description: 'Fetch latest time-series value from database' + name: 'rule-node-config.time-series-type', + description: 'rule-node-config.time-series-type-description' } ], [ ArgumentType.CONSTANT, { - name: 'tb.rulenode.constant-type', - description: 'Define constant value' + name: 'rule-node-config.constant-type', + description: 'rule-node-config.constant-type-description' } ] ]); @@ -786,29 +786,29 @@ export const ArgumentTypeResultMap = new Map([ - [AttributeScope.SHARED_SCOPE, 'tb.rulenode.shared-scope'], - [AttributeScope.SERVER_SCOPE, 'tb.rulenode.server-scope'], - [AttributeScope.CLIENT_SCOPE, 'tb.rulenode.client-scope'] + [AttributeScope.SHARED_SCOPE, 'rule-node-config.shared-scope'], + [AttributeScope.SERVER_SCOPE, 'rule-node-config.server-scope'], + [AttributeScope.CLIENT_SCOPE, 'rule-node-config.client-scope'] ]); export enum PresenceMonitoringStrategy { @@ -847,14 +847,14 @@ export const PresenceMonitoringStrategiesData = new Map
    - tb.rulenode.new-originator + rule-node-config.new-originator @@ -37,7 +37,7 @@
    -
    @@ -49,11 +49,11 @@ class="mat-mdc-form-field flex"> - tb.rulenode.entity-name-pattern + rule-node-config.entity-name-pattern - {{ 'tb.rulenode.entity-name-pattern-required' | translate }} + {{ 'rule-node-config.entity-name-pattern-required' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.html index 85cf878a4b..ccaa44bea1 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/copy-keys-config.component.html @@ -17,19 +17,19 @@ -->
    + matTooltip="{{ 'rule-node-config.use-regular-expression-hint' | translate }}"> help diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html index 5d5ec40580..e85ea71399 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/deduplication-config.component.html @@ -17,34 +17,34 @@ -->
    - {{'tb.rulenode.interval' | translate}} + {{'rule-node-config.interval' | translate}} - {{'tb.rulenode.interval-required' | translate}} + {{'rule-node-config.interval-required' | translate}} - {{'tb.rulenode.interval-min-error' | translate}} + {{'rule-node-config.interval-min-error' | translate}} help + matTooltip="{{ 'rule-node-config.interval-hint' | translate }}">help
    -
    tb.rulenode.strategy
    +
    rule-node-config.strategy
    {{ deduplicationStrategiesTranslations.get(strategy) | translate }} - - - @@ -58,40 +58,40 @@
    - tb.rulenode.advanced-settings + rule-node-config.advanced-settings
    - {{'tb.rulenode.max-pending-msgs' | translate}} + {{'rule-node-config.max-pending-msgs' | translate}} - {{'tb.rulenode.max-pending-msgs-required' | translate}} + {{'rule-node-config.max-pending-msgs-required' | translate}} - {{'tb.rulenode.max-pending-msgs-max-error' | translate}} + {{'rule-node-config.max-pending-msgs-max-error' | translate}} - {{'tb.rulenode.max-pending-msgs-min-error' | translate}} + {{'rule-node-config.max-pending-msgs-min-error' | translate}} help + matTooltip="{{ 'rule-node-config.max-pending-msgs-hint' | translate }}">help - {{'tb.rulenode.max-retries' | translate}} + {{'rule-node-config.max-retries' | translate}} - {{'tb.rulenode.max-retries-required' | translate}} + {{'rule-node-config.max-retries-required' | translate}} - {{'tb.rulenode.max-retries-max-error' | translate}} + {{'rule-node-config.max-retries-max-error' | translate}} - {{'tb.rulenode.max-retries-min-error' | translate}} + {{'rule-node-config.max-retries-min-error' | translate}} help + matTooltip="{{ 'rule-node-config.max-retries-hint' | translate }}">help
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.html index 23737bab9f..2bab63f4d6 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/delete-keys-config.component.html @@ -17,18 +17,18 @@ -->
    + matTooltip="{{ 'rule-node-config.use-regular-expression-delete-hint' | translate }}"> help diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.html index c1d3c8e2e4..94f8046b1b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/node-json-path-config.component.html @@ -17,9 +17,9 @@ -->
    - {{ 'tb.rulenode.json-path-expression' | translate }} + {{ 'rule-node-config.json-path-expression' | translate }} - {{ 'tb.rulenode.json-path-expression-hint' | translate }} - {{ 'tb.rulenode.json-path-expression-required' | translate }} + {{ 'rule-node-config.json-path-expression-hint' | translate }} + {{ 'rule-node-config.json-path-expression-required' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.html index 3099a31e4e..7543875f19 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/rename-keys-config.component.html @@ -16,7 +16,7 @@ -->
    -
    tb.rulenode.rename-keys-in
    +
    rule-node-config.rename-keys-in
    @@ -28,13 +28,13 @@
    + requiredText="{{'rule-node-config.attr-mapping-required' | translate}}" + keyText="{{'rule-node-config.current-key-name' | translate}}" + keyRequiredText="{{'rule-node-config.key-name-required' | translate}}" + valText="{{'rule-node-config.new-key-name' | translate}}" + valRequiredText="{{'rule-node-config.new-key-name-required' | translate}}">
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts index 7e462ee039..848a9dd2e9 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/script-config.component.ts @@ -46,7 +46,7 @@ export class TransformScriptConfigComponent extends RuleNodeConfigurationCompone readonly hasScript = true; - readonly testScriptLabel = 'tb.rulenode.test-transformer-function'; + readonly testScriptLabel = 'rule-node-config.test-transformer-function'; constructor(private fb: FormBuilder, private nodeScriptTestService: NodeScriptTestService, @@ -104,7 +104,7 @@ export class TransformScriptConfigComponent extends RuleNodeConfigurationCompone this.nodeScriptTestService.testNodeScript( script, 'update', - this.translate.instant('tb.rulenode.transformer'), + this.translate.instant('rule-node-config.transformer'), 'Transform', ['msg', 'metadata', 'msgType'], this.ruleNodeId, diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html index 87106d836d..373a4c6b57 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.html @@ -17,13 +17,13 @@ -->
    -
    tb.rulenode.email-sender
    +
    rule-node-config.email-sender
    - tb.rulenode.from-template + rule-node-config.from-template - {{ 'tb.rulenode.email-from-template-hint' | translate }} + {{ 'rule-node-config.email-from-template-hint' | translate }}
    @@ -33,25 +33,25 @@ tb-help-popup-placement="right" trigger-style="letter-spacing:0.25px; font-size:12px;" [tb-help-popup-style]="{maxWidth: '820px'}" - trigger-text="{{ 'tb.key-val.see-examples' | translate }}">
    + trigger-text="{{ 'rule-node-config.key-val.see-examples' | translate }}">
    - {{ 'tb.rulenode.from-template-required' | translate }} + {{ 'rule-node-config.from-template-required' | translate }}
    -
    tb.rulenode.recipients
    - rule-node-config.recipients
    +
    - tb.rulenode.to-template + rule-node-config.to-template - {{ 'tb.rulenode.to-template-required' | translate }} + {{ 'rule-node-config.to-template-required' | translate }} - tb.rulenode.cc-template + rule-node-config.cc-template - tb.rulenode.bcc-template + rule-node-config.bcc-template - {{ 'tb.rulenode.subject-template-required' | translate }} + {{ 'rule-node-config.subject-template-required' | translate }} - tb.rulenode.mail-body-type + rule-node-config.mail-body-type @@ -118,12 +118,12 @@ - tb.rulenode.body-type-template + rule-node-config.body-type-template - tb.mail-body-type.after-template-evaluation-hint + rule-node-config.mail-body-types.after-template-evaluation-hint - tb.rulenode.body-template + rule-node-config.body-template - {{ 'tb.rulenode.body-template-required' | translate }} + {{ 'rule-node-config.body-template-required' | translate }}
    diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts index 3c922a7067..97282025fd 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/to-email-config.component.ts @@ -29,18 +29,18 @@ export class ToEmailConfigComponent extends RuleNodeConfigurationComponent { toEmailConfigForm: FormGroup; mailBodyTypes = [ { - name: 'tb.mail-body-type.plain-text', - description: 'tb.mail-body-type.plain-text-description', + name: 'rule-node-config.mail-body-types.plain-text', + description: 'rule-node-config.mail-body-types.plain-text-description', value: 'false', }, { - name: 'tb.mail-body-type.html', - description: 'tb.mail-body-type.html-text-description', + name: 'rule-node-config.mail-body-types.html', + description: 'rule-node-config.mail-body-types.html-text-description', value: 'true', }, { - name: 'tb.mail-body-type.use-body-type-template', - description: 'tb.mail-body-type.dynamic-text-description', + name: 'rule-node-config.mail-body-types.use-body-type-template', + description: 'rule-node-config.mail-body-types.dynamic-text-description', value: 'dynamic', } ]; 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 cbae98683c..2fb67adbba 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -4359,6 +4359,741 @@ "queue-hint": "Select a queue for message forwarding to another queue. 'Main' queue is used by default.", "queue-singleton-hint": "Select a queue for message forwarding in multi-instance environments. 'Main' queue is used by default." }, + "rule-node-config": { + "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.", + "max-relation-level-invalid": "Value should be an integer.", + "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", + "fields-mapping-hint": "If the message field is set to $entityId, the message originator's id will be saved to the specified table column.", + "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.", + "default-ttl-zero-hint": "TTL will not be applied if its value is set to 0.", + "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": "Period in seconds", + "period-seconds-required": "Period is required.", + "generation-frequency-seconds": "Generation frequency in seconds", + "generation-frequency-required": "Generation frequency is required.", + "min-generation-frequency-message": "Only 1 second minimum is allowed.", + "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", + "current-tenant": "Current Tenant", + "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.", + "memory-buffer-size-range": "Memory buffer size must be between 0 and {{max}} KB", + "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.", + "int-range": "Value must not exceed the maximum integer limit (2147483648)", + "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": "You should 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": "The table must be created in your Cassandra cluster and its name must start with the prefix 'cs_tb_' to avoid the data insertion to the common TB tables. Enter the table name here without the 'cs_tb_' prefix.", + "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", + "attribute-type-description": "Fetch attribute value from database", + "attribute-type-result-description": "Store result as an entity attribute in the database", + "constant-type": "Constant", + "constant-type-description": "Define constant value", + "time-series-type": "Time series", + "time-series-type-description": "Fetch latest time-series value from database", + "time-series-type-result-description": "Store result as an entity time-series in the database", + "message-body-type": "Message", + "message-body-type-description": "Fetch argument value from incoming message", + "message-body-type-result-description": "Add result to the outgoing message", + "message-metadata-type": "Metadata", + "message-metadata-type-description": "Fetch argument value from incoming message metadata", + "message-metadata-result-description": "Add result to the outgoing message 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-types": { + "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." + } + }, "timezone": { "timezone": "Time zone", "select-timezone": "Select time zone", @@ -4481,734 +5216,6 @@ "too-many-requests": "Too many requests", "too-many-updates": "Too many updates" }, - "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.", - "max-relation-level-invalid": "Value should be an integer.", - "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", - "fields-mapping-hint": "If the message field is set to $entityId, the message originator's id will be saved to the specified table column.", - "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.", - "default-ttl-zero-hint": "TTL will not be applied if its value is set to 0.", - "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": "Period in seconds", - "period-seconds-required": "Period is required.", - "generation-frequency-seconds": "Generation frequency in seconds", - "generation-frequency-required": "Generation frequency is required.", - "min-generation-frequency-message": "Only 1 second minimum is allowed.", - "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", - "current-tenant": "Current Tenant", - "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.", - "memory-buffer-size-range": "Memory buffer size must be between 0 and {{max}} KB", - "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.", - "int-range": "Value must not exceed the maximum integer limit (2147483648)", - "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": "You should 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": "The table must be created in your Cassandra cluster and its name must start with the prefix 'cs_tb_' to avoid the data insertion to the common TB tables. Enter the table name here without the 'cs_tb_' prefix.", - "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." - } - }, "tenant": { "tenant": "Tenant", "tenants": "Tenants", From 4cc01d58c057fc36abcff7da9c52e1cd6a439b06 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Tue, 14 Jan 2025 12:43:47 +0200 Subject: [PATCH 07/13] UI: Remove rule node config map; Add new function extractComponentsFromModule --- .../src/app/core/http/rule-chain.service.ts | 4 +- .../app/core/services/resources.service.ts | 38 +++++++++++++++++- .../action/action-rule-node-config.module.ts | 26 ------------ .../enrichment-rule-node-core.module.ts | 13 ------ .../external-rule-node-config.module.ts | 16 -------- .../filter/filter-rule-node-config.module.ts | 11 ----- .../flow/flow-rule-node-config.module.ts | 5 --- .../rule-node/rule-node-config.module.ts | 40 ++++--------------- .../transformation-rule-node-config.module.ts | 11 ----- 9 files changed, 45 insertions(+), 119 deletions(-) diff --git a/ui-ngx/src/app/core/http/rule-chain.service.ts b/ui-ngx/src/app/core/http/rule-chain.service.ts index 37a9f8c1af..88bc4286dc 100644 --- a/ui-ngx/src/app/core/http/rule-chain.service.ts +++ b/ui-ngx/src/app/core/http/rule-chain.service.ts @@ -184,8 +184,8 @@ export class RuleChainService { return this.http.post(url, inputParams, defaultHttpOptionsFromConfig(config)); } - public registemSystemRuleNodeConfigComponent(componentMap: Record>) { - this.systemRuleNodeConfigComponents = componentMap; + public registerSystemRuleNodeConfigModule(module: any) { + this.systemRuleNodeConfigComponents = this.resourcesService.extractComponentsFromModule(module, true); } private loadRuleNodeComponents(ruleChainType: RuleChainType, config?: RequestConfig): Observable> { diff --git a/ui-ngx/src/app/core/services/resources.service.ts b/ui-ngx/src/app/core/services/resources.service.ts index f5cba07a47..38bb343aae 100644 --- a/ui-ngx/src/app/core/services/resources.service.ts +++ b/ui-ngx/src/app/core/services/resources.service.ts @@ -31,7 +31,7 @@ import { forkJoin, from, Observable, ReplaySubject, throwError } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { IModulesMap } from '@modules/common/modules-map.models'; import { TbResourceId } from '@shared/models/id/tb-resource-id'; -import { isObject } from '@core/utils'; +import { camelCase, isObject } from '@core/utils'; import { AuthService } from '@core/auth/auth.service'; import { select, Store } from '@ngrx/store'; import { selectIsAuthenticated } from '@core/auth/auth.selectors'; @@ -51,6 +51,8 @@ export interface ModulesWithComponents { standaloneComponents: ɵComponentDef[]; } +export type ComponentsSelectorMap = Record>; + export const flatModulesWithComponents = (modulesWithComponentsList: ModulesWithComponents[]): ModulesWithComponents => { const modulesWithComponents: ModulesWithComponents = { modules: [], @@ -91,6 +93,17 @@ export const componentTypeBySelector = (modulesWithComponents: ModulesWithCompon const matchesSelector = (selectors: ɵCssSelectorList, selector: string) => selectors.some(s => s.some(s1 => typeof s1 === 'string' && s1 === selector)); +const extractSelectorFromComponent = (comp: ɵComponentDef): string => { + for (const selectors of comp.selectors) { + for (const selector of selectors) { + if (typeof selector === 'string') { + return selector; + } + } + } + return null; +} + @Injectable({ providedIn: 'root' }) @@ -252,6 +265,27 @@ export class ResourcesService { ); } + public extractComponentsFromModule(module: any, isCamelCaseSelector = false): ComponentsSelectorMap { + const modulesWithComponents = this.extractModulesWithComponents(module); + const componentMap = {}; + + const processComponents = (components: Array<ɵComponentDef>) => { + components.forEach(item => { + let selector = extractSelectorFromComponent(item); + if (isCamelCaseSelector) { + selector = camelCase(selector); + } + componentMap[selector] = item.type; + }); + }; + + processComponents(modulesWithComponents.standaloneComponents); + + modulesWithComponents.modules.forEach(module => { + processComponents(module.components); + }) + return componentMap; + } private extractModulesWithComponents(module: any, modulesWithComponents: ModulesWithComponents = { @@ -284,7 +318,7 @@ export class ResourcesService { modulesWithComponents.standaloneComponents.push(component); } } else { - this.extractModulesWithComponents(module, modulesWithComponents, visitedModules); + this.extractModulesWithComponents(element, modulesWithComponents, visitedModules); } } } else if (ɵNG_COMP_DEF in module) { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts index 3e78ee4c46..17307cb341 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts @@ -103,29 +103,3 @@ import { SendRestApiCallReplyConfigComponent } from './send-rest-api-call-reply- }) export class ActionRuleNodeConfigModule { } - -export const actionRuleNodeConfigComponentsMap: Record> = { - 'tbActionNodeAssignToCustomerConfig': AssignCustomerConfigComponent, - 'tbActionNodeAttributesConfig': AttributesConfigComponent, - 'tbActionNodeClearAlarmConfig': ClearAlarmConfigComponent, - 'tbActionNodeCreateAlarmConfig': CreateAlarmConfigComponent, - 'tbActionNodeCreateRelationConfig': CreateRelationConfigComponent, - 'tbActionNodeDeleteAttributesConfig': DeleteAttributesConfigComponent, - 'tbActionNodeDeleteRelationConfig': DeleteRelationConfigComponent, - 'tbActionNodeDeviceProfileConfig': DeviceProfileConfigComponent, - 'tbActionNodeDeviceStateConfig': DeviceStateConfigComponent, - 'tbActionNodeGeneratorConfig': GeneratorConfigComponent, - 'tbActionNodeGpsGeofencingConfig': GpsGeoActionConfigComponent, - 'tbActionNodeLogConfig': LogConfigComponent, - 'tbActionNodeMathFunctionConfig': MathFunctionConfigComponent, - 'tbActionNodeMsgCountConfig': MsgCountConfigComponent, - 'tbActionNodeMsgDelayConfig': MsgDelayConfigComponent, - 'tbActionNodePushToCloudConfig': PushToCloudConfigComponent, - 'tbActionNodePushToEdgeConfig': PushToEdgeConfigComponent, - 'tbActionNodeRpcReplyConfig': RpcReplyConfigComponent, - 'tbActionNodeRpcRequestConfig': RpcRequestConfigComponent, - 'tbActionNodeCustomTableConfig': SaveToCustomTableConfigComponent, - 'tbActionNodeSendRestApiCallReplyConfig': SendRestApiCallReplyConfigComponent, - 'tbActionNodeTimeseriesConfig': TimeseriesConfigComponent, - 'tbActionNodeUnAssignToCustomerConfig': UnassignCustomerConfigComponent -}; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/enrichment-rule-node-core.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/enrichment-rule-node-core.module.ts index 987389feb8..7d614ecd96 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/enrichment-rule-node-core.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/enrichment-rule-node-core.module.ts @@ -62,16 +62,3 @@ import { FetchDeviceCredentialsConfigComponent } from './fetch-device-credential }) export class EnrichmentRuleNodeCoreModule { } - -export const enrichmentRuleNodeConfigComponentsMap: Record> = { - 'tbEnrichmentNodeCalculateDeltaConfig': CalculateDeltaConfigComponent, - 'tbEnrichmentNodeCustomerAttributesConfig': CustomerAttributesConfigComponent, - 'tbEnrichmentNodeDeviceAttributesConfig': DeviceAttributesConfigComponent, - 'tbEnrichmentNodeEntityDetailsConfig': EntityDetailsConfigComponent, - 'tbEnrichmentNodeFetchDeviceCredentialsConfig': FetchDeviceCredentialsConfigComponent, - 'tbEnrichmentNodeGetTelemetryFromDatabase': GetTelemetryFromDatabaseConfigComponent, - 'tbEnrichmentNodeOriginatorAttributesConfig': OriginatorAttributesConfigComponent, - 'tbEnrichmentNodeOriginatorFieldsConfig': OriginatorFieldsConfigComponent, - 'tbEnrichmentNodeRelatedAttributesConfig': RelatedAttributesConfigComponent, - 'tbEnrichmentNodeTenantAttributesConfig': TenantAttributesConfigComponent -} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts index 38395b9dac..c3c8c2ca2c 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts @@ -73,19 +73,3 @@ import { LambdaConfigComponent } from './lambda-config.component'; }) export class ExternalRuleNodeConfigModule { } - -export const externalRuleNodeConfigComponentsMap: Record> = { - 'tbExternalNodeAzureIotHubConfig': AzureIotHubConfigComponent, - 'tbExternalNodeKafkaConfig': KafkaConfigComponent, - 'tbExternalNodeLambdaConfig': LambdaConfigComponent, - 'tbExternalNodeMqttConfig': MqttConfigComponent, - 'tbExternalNodeNotificationConfig': NotificationConfigComponent, - 'tbExternalNodePubSubConfig': PubSubConfigComponent, - 'tbExternalNodeRabbitMqConfig': RabbitMqConfigComponent, - 'tbExternalNodeRestApiCallConfig': RestApiCallConfigComponent, - 'tbExternalNodeSendEmailConfig': SendEmailConfigComponent, - 'tbExternalNodeSendSmsConfig': SendSmsConfigComponent, - 'tbExternalNodeSlackConfig': SlackConfigComponent, - 'tbExternalNodeSnsConfig': SnsConfigComponent, - 'tbExternalNodeSqsConfig': SqsConfigComponent -} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts index ca0aaffd71..bb3636811b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts @@ -56,14 +56,3 @@ import { CommonRuleNodeConfigModule } from '../common/common-rule-node-config.mo }) export class FilterRuleNodeConfigModule { } - -export const filterRuleNodeConfigComponentsMap: Record> = { - 'tbFilterNodeCheckAlarmStatusConfig': CheckAlarmStatusComponent, - 'tbFilterNodeCheckMessageConfig': CheckMessageConfigComponent, - 'tbFilterNodeCheckRelationConfig': CheckRelationConfigComponent, - 'tbFilterNodeGpsGeofencingConfig': GpsGeoFilterConfigComponent, - 'tbFilterNodeMessageTypeConfig': MessageTypeConfigComponent, - 'tbFilterNodeOriginatorTypeConfig': OriginatorTypeConfigComponent, - 'tbFilterNodeScriptConfig': ScriptConfigComponent, - 'tbFilterNodeSwitchConfig': SwitchConfigComponent -} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts index 2ee36f71fc..8a703ca9d2 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts @@ -36,8 +36,3 @@ import { RuleChainOutputComponent } from './rule-chain-output.component'; }) export class FlowRuleNodeConfigModule { } - -export const flowRuleNodeConfigComponentsMap: Record> = { - 'tbFlowNodeRuleChainInputConfig': RuleChainInputComponent, - 'tbFlowNodeRuleChainOutputConfig': RuleChainOutputComponent -} diff --git a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts index f960777220..86512eceea 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/rule-node-config.module.ts @@ -14,35 +14,18 @@ /// limitations under the License. /// -import { NgModule, Type } from '@angular/core'; +import { NgModule } from '@angular/core'; import { EmptyConfigComponent } from './empty-config.component'; import { CommonModule } from '@angular/common'; import { SharedModule } from '@shared/shared.module'; +import { ActionRuleNodeConfigModule } from '@home/components/rule-node/action/action-rule-node-config.module'; +import { FilterRuleNodeConfigModule } from '@home/components/rule-node/filter/filter-rule-node-config.module'; +import { EnrichmentRuleNodeCoreModule } from '@home/components/rule-node/enrichment/enrichment-rule-node-core.module'; +import { ExternalRuleNodeConfigModule } from '@home/components/rule-node/external/external-rule-node-config.module'; import { - actionRuleNodeConfigComponentsMap, - ActionRuleNodeConfigModule -} from '@home/components/rule-node/action/action-rule-node-config.module'; -import { - filterRuleNodeConfigComponentsMap, - FilterRuleNodeConfigModule -} from '@home/components/rule-node/filter/filter-rule-node-config.module'; -import { - enrichmentRuleNodeConfigComponentsMap, - EnrichmentRuleNodeCoreModule -} from '@home/components/rule-node/enrichment/enrichment-rule-node-core.module'; -import { - externalRuleNodeConfigComponentsMap, - ExternalRuleNodeConfigModule -} from '@home/components/rule-node/external/external-rule-node-config.module'; -import { - transformationRuleNodeConfigComponentsMap, TransformationRuleNodeConfigModule } from '@home/components/rule-node/transformation/transformation-rule-node-config.module'; -import { - flowRuleNodeConfigComponentsMap, - FlowRuleNodeConfigModule -} from '@home/components/rule-node/flow/flow-rule-node-config.module'; -import { IRuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; +import { FlowRuleNodeConfigModule } from '@home/components/rule-node/flow/flow-rule-node-config.module'; import { RuleChainService } from '@core/http/rule-chain.service'; @NgModule({ @@ -65,15 +48,6 @@ import { RuleChainService } from '@core/http/rule-chain.service'; }) export class RuleNodeConfigModule { constructor(private ruleChainService: RuleChainService) { - const ruleNodeConfigComponentsMap: Record> = { - ...actionRuleNodeConfigComponentsMap, - ...enrichmentRuleNodeConfigComponentsMap, - ...externalRuleNodeConfigComponentsMap, - ...filterRuleNodeConfigComponentsMap, - ...flowRuleNodeConfigComponentsMap, - ...transformationRuleNodeConfigComponentsMap, - 'tbNodeEmptyConfig': EmptyConfigComponent - }; - this.ruleChainService.registemSystemRuleNodeConfigComponent(ruleNodeConfigComponentsMap); + this.ruleChainService.registerSystemRuleNodeConfigModule(this.constructor); } } diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts index a25495d7b4..76ba7934d6 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts @@ -57,14 +57,3 @@ import { ScriptConfigComponent } from '@home/components/rule-node/filter/script- }) export class TransformationRuleNodeConfigModule { } - -export const transformationRuleNodeConfigComponentsMap: Record> = { - 'tbTransformationNodeChangeOriginatorConfig': ChangeOriginatorConfigComponent, - 'tbTransformationNodeCopyKeysConfig': CopyKeysConfigComponent, - 'tbTransformationNodeDeduplicationConfig': DeduplicationConfigComponent, - 'tbTransformationNodeDeleteKeysConfig': DeleteKeysConfigComponent, - 'tbTransformationNodeJsonPathConfig': NodeJsonPathConfigComponent, - 'tbTransformationNodeRenameKeysConfig': RenameKeysConfigComponent, - 'tbTransformationNodeScriptConfig': ScriptConfigComponent, - 'tbTransformationNodeToEmailConfig': ToEmailConfigComponent -} From 042ab7e807327117ca1453c0bdff81afdf076360 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 15 Jan 2025 17:20:05 +0200 Subject: [PATCH 08/13] UI: Add tailwinds constants from rule node config --- ui-ngx/tailwind.config.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui-ngx/tailwind.config.js b/ui-ngx/tailwind.config.js index e53b102710..b71b4eb235 100644 --- a/ui-ngx/tailwind.config.js +++ b/ui-ngx/tailwind.config.js @@ -93,6 +93,7 @@ module.exports = { '0.75': '0.1875rem', '1.25': '0.3125rem', '3.75': '0.9375rem', + '5.5': '1.375rem', '6.25': '1.5625rem' }, minHeight: { @@ -152,6 +153,7 @@ module.exports = { '7.5': '1.875rem', '25': '6.25rem', '37.5': '9.375rem', + '50': '12.5rem', '62.5': '15.625rem', '72.5': '18.125rem' }, From 0fb27016ec18cd512a18ff08eec69edfa4ce5712 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Fri, 17 Jan 2025 10:58:19 +0200 Subject: [PATCH 09/13] UI: Add unsubscribe valueChanges in rule node --- .../action/attributes-config.component.ts | 5 +- .../action/create-alarm-config.component.ts | 5 +- .../delete-attributes-config.component.ts | 5 +- .../common/alarm-status-select.component.ts | 20 +++----- .../common/arguments-map-config.component.ts | 36 +++++++-------- .../common/credentials-config.component.ts | 46 ++++++++----------- ...device-relations-query-config.component.ts | 12 +++-- .../common/kv-map-config-old.component.ts | 43 ++++++++--------- .../common/kv-map-config.component.ts | 19 +++----- .../math-function-autocomplete.component.ts | 4 +- .../common/message-types-config.component.ts | 2 +- .../common/msg-metadata-chip.component.ts | 20 +++----- ...put-message-type-autocomplete.component.ts | 18 +++----- .../relations-query-config-old.component.ts | 17 +++---- .../relations-query-config.component.ts | 17 +++---- .../common/select-attributes.component.ts | 20 +++----- .../common/sv-map-config.component.ts | 42 ++++++----------- .../src/app/shared/models/rule-node.models.ts | 2 +- 18 files changed, 145 insertions(+), 188 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts index a60a4ae40e..29b5dd2bc5 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/attributes-config.component.ts @@ -18,6 +18,7 @@ import { Component } from '@angular/core'; import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models'; import { AttributeScope, telemetryTypeTranslations } from '@app/shared/models/telemetry/telemetry.models'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-action-node-attributes-config', @@ -48,7 +49,9 @@ export class AttributesConfigComponent extends RuleNodeConfigurationComponent { updateAttributesOnlyOnValueChange: [configuration ? configuration.updateAttributesOnlyOnValueChange : false, []] }); - this.attributesConfigForm.get('scope').valueChanges.subscribe((value) => { + this.attributesConfigForm.get('scope').valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe((value) => { if (value !== AttributeScope.SHARED_SCOPE) { this.attributesConfigForm.get('notifyDevice').patchValue(false, {emitEvent: false}); } diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts index a68eedfbfc..738ec589be 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/create-alarm-config.component.ts @@ -29,6 +29,7 @@ import { import type { JsFuncComponent } from '@app/shared/components/js-func.component'; import { AlarmSeverity, alarmSeverityTranslations } from '@app/shared/models/alarm.models'; import { DebugRuleNodeEventBody } from '@shared/models/event.models'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-action-node-create-alarm-config', @@ -83,7 +84,9 @@ export class CreateAlarmConfigComponent extends RuleNodeConfigurationComponent { dynamicSeverity: false }); - this.createAlarmConfigForm.get('dynamicSeverity').valueChanges.subscribe((dynamicSeverity) => { + this.createAlarmConfigForm.get('dynamicSeverity').valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe((dynamicSeverity) => { if(dynamicSeverity){ this.createAlarmConfigForm.get('severity').patchValue('',{emitEvent:false}); } else { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts index 758e0ecb48..b61f9aa7c1 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/delete-attributes-config.component.ts @@ -20,6 +20,7 @@ import { MatChipGrid, MatChipInputEvent } from '@angular/material/chips'; import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@app/shared/models/rule-node.models'; import { AttributeScope, telemetryTypeTranslations } from '@shared/models/telemetry/telemetry.models'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-action-node-delete-attributes-config', @@ -51,7 +52,9 @@ export class DeleteAttributesConfigComponent extends RuleNodeConfigurationCompon notifyDevice: [configuration ? configuration.notifyDevice : false, []] }); - this.deleteAttributesConfigForm.get('scope').valueChanges.subscribe((value) => { + this.deleteAttributesConfigForm.get('scope').valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe((value) => { if (value !== AttributeScope.SHARED_SCOPE) { this.deleteAttributesConfigForm.get('notifyDevice').patchValue(false, {emitEvent: false}); } diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts index 923a4f13fc..f92f09b428 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/alarm-status-select.component.ts @@ -14,11 +14,10 @@ /// limitations under the License. /// -import { Component, forwardRef, OnDestroy, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, OnInit } from '@angular/core'; import { AlarmStatus, alarmStatusTranslations, PageComponent } from '@shared/public-api'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; -import { takeUntil } from 'rxjs/operators'; -import { Subject } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-alarm-status-select', @@ -31,17 +30,17 @@ import { Subject } from 'rxjs'; }] }) -export class AlarmStatusSelectComponent extends PageComponent implements OnInit, ControlValueAccessor, OnDestroy { +export class AlarmStatusSelectComponent extends PageComponent implements OnInit, ControlValueAccessor { public alarmStatusGroup: FormGroup; private propagateChange = null; - private destroy$ = new Subject(); readonly alarmStatus = AlarmStatus; readonly alarmStatusTranslations = alarmStatusTranslations; - constructor(private fb: FormBuilder) { + constructor(private fb: FormBuilder, + private destroyRef: DestroyRef) { super(); } @@ -51,7 +50,7 @@ export class AlarmStatusSelectComponent extends PageComponent implements OnInit, }); this.alarmStatusGroup.get('alarmStatus').valueChanges.pipe( - takeUntil(this.destroy$) + takeUntilDestroyed(this.destroyRef) ).subscribe((value) => { this.propagateChange(value); }); @@ -69,12 +68,7 @@ export class AlarmStatusSelectComponent extends PageComponent implements OnInit, this.propagateChange = fn; } - registerOnTouched(fn: any): void { - } - - ngOnDestroy() { - this.destroy$.next(); - this.destroy$.complete(); + registerOnTouched(_fn: any): void { } writeValue(value: Array): void { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts index 3b2e99cf96..3e6d5826f8 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/arguments-map-config.component.ts @@ -14,12 +14,11 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormArray, FormBuilder, - FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, @@ -27,7 +26,6 @@ import { Validators } from '@angular/forms'; import { PageComponent } from '@shared/public-api'; -import { Subscription } from 'rxjs'; import { CdkDragDrop } from '@angular/cdk/drag-drop'; import { ArgumentName, @@ -38,6 +36,7 @@ import { MathFunction, MathFunctionMap } from './../rule-node-config.models'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-arguments-map-config', @@ -56,7 +55,7 @@ import { } ] }) -export class ArgumentsMapConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, OnDestroy, Validator { +export class ArgumentsMapConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator { @Input() disabled: boolean; @@ -90,9 +89,8 @@ export class ArgumentsMapConfigComponent extends PageComponent implements Contro private propagateChange = null; - private valueChangeSubscription: Subscription[] = []; - - constructor(private fb: FormBuilder) { + constructor(private fb: FormBuilder, + private destroyRef: DestroyRef) { super(); } @@ -101,9 +99,11 @@ export class ArgumentsMapConfigComponent extends PageComponent implements Contro arguments: this.fb.array([]) }); - this.valueChangeSubscription.push(this.argumentsFormGroup.valueChanges.subscribe(() => { + this.argumentsFormGroup.valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe(() => { this.updateModel(); - })); + }); this.setupArgumentsFormGroup(); } @@ -124,7 +124,7 @@ export class ArgumentsMapConfigComponent extends PageComponent implements Contro this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } setDisabledState(isDisabled: boolean): void { @@ -138,13 +138,7 @@ export class ArgumentsMapConfigComponent extends PageComponent implements Contro } } - ngOnDestroy() { - if (this.valueChangeSubscription.length) { - this.valueChangeSubscription.forEach(sub => sub.unsubscribe()); - } - } - - writeValue(argumentsList): void { + writeValue(argumentsList: Array): void { const argumentsControls: Array = []; if (argumentsList) { argumentsList.forEach((property, index) => { @@ -167,7 +161,7 @@ export class ArgumentsMapConfigComponent extends PageComponent implements Contro argumentsFormArray.push(argumentControl, {emitEvent}); } - public validate(c: FormControl) { + public validate() { if (!this.argumentsFormGroup.valid) { return { argumentsRequired: true @@ -203,11 +197,13 @@ export class ArgumentsMapConfigComponent extends PageComponent implements Contro defaultValue: [property?.defaultValue ? property?.defaultValue : null] }); this.updateArgumentControlValidators(argumentControl); - this.valueChangeSubscription.push(argumentControl.get('type').valueChanges.subscribe(() => { + argumentControl.get('type').valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe(() => { this.updateArgumentControlValidators(argumentControl); argumentControl.get('attributeScope').updateValueAndValidity({emitEvent: false}); argumentControl.get('defaultValue').updateValueAndValidity({emitEvent: false}); - })); + }); return argumentControl; } diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts index 97f0ba0846..95ed59683d 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/credentials-config.component.ts @@ -14,11 +14,10 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { ControlValueAccessor, FormBuilder, - FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, @@ -27,12 +26,11 @@ import { ValidatorFn, Validators } from '@angular/forms'; -import { AppState, isDefinedAndNotNull } from '@core/public-api'; +import { isDefinedAndNotNull } from '@core/public-api'; import { PageComponent } from '@shared/public-api'; -import { Store } from '@ngrx/store'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { credentialsType, credentialsTypes, credentialsTypeTranslations } from '../rule-node-config.models'; -import { Subscription } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; interface CredentialsConfig { type: credentialsType; @@ -63,12 +61,10 @@ interface CredentialsConfig { } ] }) -export class CredentialsConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy, OnChanges { +export class CredentialsConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator, OnChanges { credentialsConfigFormGroup: FormGroup; - subscriptions: Subscription[] = []; - private requiredValue: boolean; get required(): boolean { @@ -91,9 +87,9 @@ export class CredentialsConfigComponent extends PageComponent implements Control private propagateChange = (_: any) => {}; - constructor(protected store: Store, - private fb: FormBuilder) { - super(store); + constructor(private fb: FormBuilder, + private destroyRef: DestroyRef) { + super(); } ngOnInit(): void { @@ -110,16 +106,16 @@ export class CredentialsConfigComponent extends PageComponent implements Control certFileName: [null, []] } ); - this.subscriptions.push( - this.credentialsConfigFormGroup.valueChanges.subscribe(() => { - this.updateView(); - }) - ); - this.subscriptions.push( - this.credentialsConfigFormGroup.get('type').valueChanges.subscribe(() => { - this.credentialsTypeChanged(); - }) - ); + this.credentialsConfigFormGroup.valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe(() => { + this.updateView(); + }); + this.credentialsConfigFormGroup.get('type').valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe(() => { + this.credentialsTypeChanged(); + }); } ngOnChanges(changes: SimpleChanges): void { @@ -138,10 +134,6 @@ export class CredentialsConfigComponent extends PageComponent implements Control } } - ngOnDestroy() { - this.subscriptions.forEach(s => s.unsubscribe()); - } - writeValue(credentials: CredentialsConfig | null): void { if (isDefinedAndNotNull(credentials)) { this.credentialsConfigFormGroup.reset(credentials, {emitEvent: false}); @@ -185,10 +177,10 @@ export class CredentialsConfigComponent extends PageComponent implements Control this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(): void { } - public validate(c: FormControl) { + public validate() { return this.credentialsConfigFormGroup.valid ? null : { credentialsConfig: { valid: false, diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts index 23aee0b29a..bc9f524a75 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/device-relations-query-config.component.ts @@ -14,12 +14,13 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { PageComponent } from '@shared/components/page.component'; import { EntitySearchDirection, entitySearchDirectionTranslations } from '@app/shared/models/relation.models'; import { EntityType } from '@shared/models/entity-type.models'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; interface DeviceRelationsQuery { fetchLastLevelOnly: boolean; @@ -65,7 +66,8 @@ export class DeviceRelationsQueryConfigComponent extends PageComponent implement private propagateChange = null; - constructor(private fb: FormBuilder) { + constructor(private fb: FormBuilder, + private destroyRef: DestroyRef) { super(); } @@ -77,7 +79,9 @@ export class DeviceRelationsQueryConfigComponent extends PageComponent implement relationType: [null], deviceTypes: [null, [Validators.required]] }); - this.deviceRelationsQueryFormGroup.valueChanges.subscribe((query: DeviceRelationsQuery) => { + this.deviceRelationsQueryFormGroup.valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe((query: DeviceRelationsQuery) => { if (this.deviceRelationsQueryFormGroup.valid) { this.propagateChange(query); } else { @@ -90,7 +94,7 @@ export class DeviceRelationsQueryConfigComponent extends PageComponent implement this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } setDisabledState(isDisabled: boolean): void { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts index a08394479a..1f7407c5e3 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config-old.component.ts @@ -14,13 +14,12 @@ /// limitations under the License. /// -import { Component, forwardRef, Injector, Input, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Injector, Input, OnInit } from '@angular/core'; import { AbstractControl, ControlValueAccessor, FormArray, FormBuilder, - FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, @@ -29,11 +28,9 @@ import { Validators } from '@angular/forms'; import { PageComponent } from '@shared/public-api'; -import { Store } from '@ngrx/store'; -import { AppState } from '@core/public-api'; -import { Subscription } from 'rxjs'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { TranslateService } from '@ngx-translate/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-kv-map-config-old', @@ -87,13 +84,11 @@ export class KvMapConfigOldComponent extends PageComponent implements ControlVal private propagateChange = null; - private valueChangeSubscription: Subscription = null; - - constructor(protected store: Store, - public translate: TranslateService, - public injector: Injector, - private fb: FormBuilder) { - super(store); + constructor(public translate: TranslateService, + private injector: Injector, + private fb: FormBuilder, + private destroyRef: DestroyRef) { + super(); } ngOnInit(): void { @@ -101,9 +96,15 @@ export class KvMapConfigOldComponent extends PageComponent implements ControlVal if (this.ngControl != null) { this.ngControl.valueAccessor = this; } - this.kvListFormGroup = this.fb.group({}); - this.kvListFormGroup.addControl('keyVals', - this.fb.array([])); + this.kvListFormGroup = this.fb.group({ + keyVals: this.fb.array([]) + }); + + this.kvListFormGroup.valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe(() => { + this.updateModel(); + }); } keyValsFormArray(): FormArray { @@ -114,7 +115,7 @@ export class KvMapConfigOldComponent extends PageComponent implements ControlVal this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } setDisabledState(isDisabled: boolean): void { @@ -127,9 +128,6 @@ export class KvMapConfigOldComponent extends PageComponent implements ControlVal } writeValue(keyValMap: { [key: string]: string }): void { - if (this.valueChangeSubscription) { - this.valueChangeSubscription.unsubscribe(); - } const keyValsControls: Array = []; if (keyValMap) { for (const property of Object.keys(keyValMap)) { @@ -141,10 +139,7 @@ export class KvMapConfigOldComponent extends PageComponent implements ControlVal } } } - this.kvListFormGroup.setControl('keyVals', this.fb.array(keyValsControls)); - this.valueChangeSubscription = this.kvListFormGroup.valueChanges.subscribe(() => { - this.updateModel(); - }); + this.kvListFormGroup.setControl('keyVals', this.fb.array(keyValsControls), {emitEvent: false}); } public removeKeyVal(index: number) { @@ -159,7 +154,7 @@ export class KvMapConfigOldComponent extends PageComponent implements ControlVal })); } - public validate(c: FormControl) { + public validate() { const kvList: { key: string; value: string }[] = this.kvListFormGroup.get('keyVals').value; if (!kvList.length && this.required) { return { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts index 042dcf94bd..f46b5e9923 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/kv-map-config.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, forwardRef, Injector, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Injector, Input, OnInit } from '@angular/core'; import { AbstractControl, ControlValueAccessor, @@ -31,7 +31,7 @@ import { } from '@angular/forms'; import { coerceBoolean } from '@shared/public-api'; import { isEqual } from '@core/public-api'; -import { Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-kv-map-config', @@ -50,10 +50,9 @@ import { Subject, takeUntil } from 'rxjs'; } ] }) -export class KvMapConfigComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy { +export class KvMapConfigComponent implements ControlValueAccessor, OnInit, Validator { private propagateChange: (value: any) => void = () => {}; - private destroy$ = new Subject(); kvListFormGroup: FormGroup; ngControl: NgControl; @@ -87,7 +86,8 @@ export class KvMapConfigComponent implements ControlValueAccessor, OnInit, Valid required = false; constructor(private injector: Injector, - private fb: FormBuilder) { + private fb: FormBuilder, + private destroyRef: DestroyRef) { } ngOnInit(): void { @@ -101,17 +101,12 @@ export class KvMapConfigComponent implements ControlValueAccessor, OnInit, Valid }, {validators: [this.propagateNestedErrors, this.oneMapRequiredValidator]}); this.kvListFormGroup.valueChanges - .pipe(takeUntil(this.destroy$)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.updateModel(); }); } - ngOnDestroy() { - this.destroy$.next(); - this.destroy$.complete(); - } - keyValsFormArray(): FormArray { return this.kvListFormGroup.get('keyVals') as FormArray; } @@ -120,7 +115,7 @@ export class KvMapConfigComponent implements ControlValueAccessor, OnInit, Valid this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } setDisabledState(isDisabled: boolean): void { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts index 1583048073..fb34cf4418 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/math-function-autocomplete.component.ts @@ -75,7 +75,7 @@ export class MathFunctionAutocompleteComponent implements ControlValueAccessor, }); this.filteredOptions = this.mathFunctionForm.get('operation').valueChanges.pipe( tap(value => { - let modelValue; + let modelValue: MathFunction; if (typeof value === 'string' && MathFunction[value]) { modelValue = MathFunction[value]; } else { @@ -101,7 +101,7 @@ export class MathFunctionAutocompleteComponent implements ControlValueAccessor, this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } setDisabledState(isDisabled: boolean): void { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts index 686c6150aa..c5d10a2d25 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/message-types-config.component.ts @@ -98,7 +98,7 @@ export class MessageTypesConfigComponent extends PageComponent implements Contro this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } ngOnInit() { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts index 066cea455e..a8e00a68e4 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/msg-metadata-chip.component.ts @@ -14,12 +14,11 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; import { FetchTo, FetchToTranslation } from '../rule-node-config.models'; -import { takeUntil } from 'rxjs/operators'; -import { Subject } from 'rxjs'; import { TranslateService } from '@ngx-translate/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-msg-metadata-chip', @@ -31,19 +30,19 @@ import { TranslateService } from '@ngx-translate/core'; }] }) -export class MsgMetadataChipComponent implements OnInit, ControlValueAccessor, OnDestroy { +export class MsgMetadataChipComponent implements OnInit, ControlValueAccessor { @Input() labelText: string; @Input() translation: Map = FetchToTranslation; private propagateChange: (value: any) => void = () => {}; - private destroy$ = new Subject(); public chipControlGroup: FormGroup; public selectOptions = []; constructor(private fb: FormBuilder, - private translate: TranslateService) {} + private translate: TranslateService, + private destroyRef: DestroyRef) {} ngOnInit(): void { this.initOptions(); @@ -52,7 +51,7 @@ export class MsgMetadataChipComponent implements OnInit, ControlValueAccessor, O }); this.chipControlGroup.get('chipControl').valueChanges.pipe( - takeUntil(this.destroy$) + takeUntilDestroyed(this.destroyRef) ).subscribe((value) => { if (value) { this.propagateChange(value); @@ -61,11 +60,6 @@ export class MsgMetadataChipComponent implements OnInit, ControlValueAccessor, O ); } - ngOnDestroy(): void { - this.destroy$.next(); - this.destroy$.complete(); - } - initOptions() { for (const key of this.translation.keys()) { this.selectOptions.push({ @@ -83,7 +77,7 @@ export class MsgMetadataChipComponent implements OnInit, ControlValueAccessor, O this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } setDisabledState(isDisabled: boolean): void { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts index 494b686ba3..b824240968 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/output-message-type-autocomplete.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnDestroy } from '@angular/core'; +import { Component, forwardRef, Input } from '@angular/core'; import { ControlValueAccessor, FormBuilder, @@ -26,7 +26,7 @@ import { } from '@angular/forms'; import { SubscriptSizing } from '@angular/material/form-field'; import { coerceBoolean } from '@shared/public-api'; -import { Subject, takeUntil } from 'rxjs'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; interface MessageType { name: string; @@ -51,7 +51,7 @@ interface MessageType { ] }) -export class OutputMessageTypeAutocompleteComponent implements ControlValueAccessor, Validator, OnDestroy { +export class OutputMessageTypeAutocompleteComponent implements ControlValueAccessor, Validator { @Input() subscriptSizing: SubscriptSizing = 'fixed'; @@ -93,7 +93,6 @@ export class OutputMessageTypeAutocompleteComponent implements ControlValueAcces private modelValue: string | null; private requiredValue: boolean; private propagateChange: (value: any) => void = () => {}; - private destroy$ = new Subject(); constructor(private fb: FormBuilder) { this.messageTypeFormGroup = this.fb.group({ @@ -101,19 +100,14 @@ export class OutputMessageTypeAutocompleteComponent implements ControlValueAcces messageType: [{value: null, disabled: true}, [Validators.maxLength(255)]] }); this.messageTypeFormGroup.get('messageTypeAlias').valueChanges - .pipe(takeUntil(this.destroy$)) + .pipe(takeUntilDestroyed()) .subscribe(value => this.updateMessageTypeValue(value)); this.messageTypeFormGroup.valueChanges - .pipe(takeUntil(this.destroy$)) + .pipe(takeUntilDestroyed()) .subscribe(() => this.updateView()); } - ngOnDestroy() { - this.destroy$.next(); - this.destroy$.complete(); - } - - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } registerOnChange(fn: any): void { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts index e89cd249f8..261b2aadc3 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config-old.component.ts @@ -14,13 +14,12 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { EntitySearchDirection, entitySearchDirectionTranslations, PageComponent } from '@shared/public-api'; -import { Store } from '@ngrx/store'; -import { AppState } from '@core/public-api'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { RelationsQuery } from '../rule-node-config.models'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-relations-query-config-old', @@ -56,9 +55,9 @@ export class RelationsQueryConfigOldComponent extends PageComponent implements C private propagateChange = null; - constructor(protected store: Store, - private fb: FormBuilder) { - super(store); + constructor(private fb: FormBuilder, + private destroyRef: DestroyRef) { + super(); } ngOnInit(): void { @@ -68,7 +67,9 @@ export class RelationsQueryConfigOldComponent extends PageComponent implements C maxLevel: [null, []], filters: [null] }); - this.relationsQueryFormGroup.valueChanges.subscribe((query: RelationsQuery) => { + this.relationsQueryFormGroup.valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe((query: RelationsQuery) => { if (this.relationsQueryFormGroup.valid) { this.propagateChange(query); } else { @@ -81,7 +82,7 @@ export class RelationsQueryConfigOldComponent extends PageComponent implements C this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } setDisabledState(isDisabled: boolean): void { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts index d17e6f891f..5ed0eadbcc 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/relations-query-config.component.ts @@ -14,13 +14,12 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { EntitySearchDirection, entitySearchDirectionTranslations, PageComponent } from '@shared/public-api'; -import { Store } from '@ngrx/store'; -import { AppState } from '@core/public-api'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { RelationsQuery } from '../rule-node-config.models'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-relations-query-config', @@ -55,9 +54,9 @@ export class RelationsQueryConfigComponent extends PageComponent implements Cont private propagateChange = null; - constructor(protected store: Store, - private fb: FormBuilder) { - super(store); + constructor(private fb: FormBuilder, + private destroyRef: DestroyRef) { + super(); } ngOnInit(): void { @@ -67,7 +66,9 @@ export class RelationsQueryConfigComponent extends PageComponent implements Cont maxLevel: [null, [Validators.min(1)]], filters: [null] }); - this.relationsQueryFormGroup.valueChanges.subscribe((query: RelationsQuery) => { + this.relationsQueryFormGroup.valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) + ).subscribe((query: RelationsQuery) => { if (this.relationsQueryFormGroup.valid) { this.propagateChange(query); } else { @@ -80,7 +81,7 @@ export class RelationsQueryConfigComponent extends PageComponent implements Cont this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } setDisabledState(isDisabled: boolean): void { diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts index fbfbb63a14..2bebd875ae 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/select-attributes.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, @@ -25,11 +25,10 @@ import { ValidatorFn, Validators } from '@angular/forms'; -import { takeUntil } from 'rxjs/operators'; -import { Subject } from 'rxjs'; import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes'; import { TranslateService } from '@ngx-translate/core'; import { isDefinedAndNotNull } from '@core/public-api'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-select-attributes', @@ -46,10 +45,9 @@ import { isDefinedAndNotNull } from '@core/public-api'; }] }) -export class SelectAttributesComponent implements OnInit, ControlValueAccessor, OnDestroy { +export class SelectAttributesComponent implements OnInit, ControlValueAccessor { private propagateChange = (v: any) => { }; - private destroy$ = new Subject(); public attributeControlGroup: FormGroup; public separatorKeysCodes = [ENTER, COMMA, SEMICOLON]; @@ -58,7 +56,8 @@ export class SelectAttributesComponent implements OnInit, ControlValueAccessor, @Input() popupHelpLink: string; constructor(public translate: TranslateService, - private fb: FormBuilder) { + private fb: FormBuilder, + private destroyRef: DestroyRef) { } ngOnInit(): void { @@ -74,7 +73,7 @@ export class SelectAttributesComponent implements OnInit, ControlValueAccessor, }); this.attributeControlGroup.valueChanges.pipe( - takeUntil(this.destroy$) + takeUntilDestroyed(this.destroyRef) ).subscribe((value) => { this.propagateChange(this.preparePropagateValue(value)); }); @@ -88,7 +87,7 @@ export class SelectAttributesComponent implements OnInit, ControlValueAccessor, } else { formatValue[key] = isDefinedAndNotNull(propagateValue[key]) ? propagateValue[key] : []; } - }; + } return formatValue; }; @@ -131,9 +130,4 @@ export class SelectAttributesComponent implements OnInit, ControlValueAccessor, this.attributeControlGroup.enable({emitEvent: false}); } } - - ngOnDestroy(): void { - this.destroy$.next(null); - this.destroy$.complete(); - } } diff --git a/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts index df9d3f0b3d..0a836fc508 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/common/sv-map-config.component.ts @@ -14,13 +14,12 @@ /// limitations under the License. /// -import { Component, forwardRef, Injector, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, DestroyRef, forwardRef, Injector, Input, OnInit } from '@angular/core'; import { AbstractControl, ControlValueAccessor, FormArray, FormBuilder, - FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, @@ -31,12 +30,10 @@ import { Validators } from '@angular/forms'; import { coerceBoolean, PageComponent } from '@shared/public-api'; -import { Store } from '@ngrx/store'; -import { AppState, isDefinedAndNotNull, isEqual } from '@core/public-api'; -import { Subject, Subscription } from 'rxjs'; +import { isDefinedAndNotNull, isEqual } from '@core/public-api'; import { TranslateService } from '@ngx-translate/core'; -import { takeUntil } from 'rxjs/operators'; import { OriginatorFieldsMappingValues, SvMapOption } from '../rule-node-config.models'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'tb-sv-map-config', @@ -55,10 +52,8 @@ import { OriginatorFieldsMappingValues, SvMapOption } from '../rule-node-config. } ] }) -export class SvMapConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator, OnDestroy { +export class SvMapConfigComponent extends PageComponent implements ControlValueAccessor, OnInit, Validator { - private destroy$ = new Subject(); - private sourceFieldSubcritption: Subscription[] = []; private propagateChange = null; svListFormGroup: FormGroup; @@ -92,11 +87,11 @@ export class SvMapConfigComponent extends PageComponent implements ControlValueA @coerceBoolean() required = false; - constructor(protected store: Store, - public translate: TranslateService, - public injector: Injector, - private fb: FormBuilder) { - super(store); + constructor(public translate: TranslateService, + private injector: Injector, + private fb: FormBuilder, + private destroyRef: DestroyRef) { + super(); } ngOnInit(): void { @@ -110,17 +105,12 @@ export class SvMapConfigComponent extends PageComponent implements ControlValueA }, {validators: [this.propagateNestedErrors, this.oneMapRequiredValidator]}); this.svListFormGroup.valueChanges - .pipe(takeUntil(this.destroy$)) + .pipe(takeUntilDestroyed(this.destroyRef)) .subscribe(() => { this.updateModel(); }); } - ngOnDestroy() { - this.destroy$.next(); - this.destroy$.complete(); - } - keyValsFormArray(): FormArray { return this.svListFormGroup.get('keyVals') as FormArray; } @@ -129,7 +119,7 @@ export class SvMapConfigComponent extends PageComponent implements ControlValueA this.propagateChange = fn; } - registerOnTouched(fn: any): void { + registerOnTouched(_fn: any): void { } setDisabledState(isDisabled: boolean): void { @@ -215,8 +205,6 @@ export class SvMapConfigComponent extends PageComponent implements ControlValueA public removeKeyVal(index: number) { this.keyValsFormArray().removeAt(index); - this.sourceFieldSubcritption[index].unsubscribe(); - this.sourceFieldSubcritption.splice(index, 1); } public addKeyVal() { @@ -228,15 +216,15 @@ export class SvMapConfigComponent extends PageComponent implements ControlValueA } private keyChangeSubscribe(formGroup: FormGroup) { - this.sourceFieldSubcritption.push(formGroup.get('key').valueChanges.pipe( - takeUntil(this.destroy$) + formGroup.get('key').valueChanges.pipe( + takeUntilDestroyed(this.destroyRef) ).subscribe((value) => { const mappedValue = OriginatorFieldsMappingValues.get(value); formGroup.get('value').patchValue(this.targetKeyPrefix + mappedValue[0].toUpperCase() + mappedValue.slice(1)); - })); + }); } - public validate(c: FormControl) { + public validate() { const svList: { key: string; value: string }[] = this.svListFormGroup.get('keyVals').value; if (!svList.length && this.required) { return { diff --git a/ui-ngx/src/app/shared/models/rule-node.models.ts b/ui-ngx/src/app/shared/models/rule-node.models.ts index 86e304b3df..471594f689 100644 --- a/ui-ngx/src/app/shared/models/rule-node.models.ts +++ b/ui-ngx/src/app/shared/models/rule-node.models.ts @@ -101,7 +101,7 @@ export abstract class RuleNodeConfigurationComponent extends PageComponent imple private configurationSet = false; private disabledValue = false; - private destroyRef = inject(DestroyRef); + protected destroyRef = inject(DestroyRef); set disabled(value: boolean) { if (this.disabledValue !== value) { From e4a216bb87a13edc3dd0eef997d30e4c91822487 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 20 Jan 2025 11:25:59 +0200 Subject: [PATCH 10/13] UI: Add generic type to extractComponentsFromModule --- ui-ngx/src/app/core/http/rule-chain.service.ts | 2 +- ui-ngx/src/app/core/services/resources.service.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/core/http/rule-chain.service.ts b/ui-ngx/src/app/core/http/rule-chain.service.ts index 88bc4286dc..c7b7c04842 100644 --- a/ui-ngx/src/app/core/http/rule-chain.service.ts +++ b/ui-ngx/src/app/core/http/rule-chain.service.ts @@ -185,7 +185,7 @@ export class RuleChainService { } public registerSystemRuleNodeConfigModule(module: any) { - this.systemRuleNodeConfigComponents = this.resourcesService.extractComponentsFromModule(module, true); + this.systemRuleNodeConfigComponents = this.resourcesService.extractComponentsFromModule(module, true); } private loadRuleNodeComponents(ruleChainType: RuleChainType, config?: RequestConfig): Observable> { diff --git a/ui-ngx/src/app/core/services/resources.service.ts b/ui-ngx/src/app/core/services/resources.service.ts index 38bb343aae..dcc6c3f8d0 100644 --- a/ui-ngx/src/app/core/services/resources.service.ts +++ b/ui-ngx/src/app/core/services/resources.service.ts @@ -51,7 +51,7 @@ export interface ModulesWithComponents { standaloneComponents: ɵComponentDef[]; } -export type ComponentsSelectorMap = Record>; +export type ComponentsSelectorMap = Record>; export const flatModulesWithComponents = (modulesWithComponentsList: ModulesWithComponents[]): ModulesWithComponents => { const modulesWithComponents: ModulesWithComponents = { @@ -265,7 +265,7 @@ export class ResourcesService { ); } - public extractComponentsFromModule(module: any, isCamelCaseSelector = false): ComponentsSelectorMap { + public extractComponentsFromModule(module: any, isCamelCaseSelector = false): ComponentsSelectorMap { const modulesWithComponents = this.extractModulesWithComponents(module); const componentMap = {}; From 76b5719e745f4425bc0ed8bb67822ab77bb43093 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 20 Jan 2025 12:28:23 +0200 Subject: [PATCH 11/13] UI: Remove systemRuleNodeConfigComponents register --- ui-ngx/src/app/core/http/rule-chain.service.ts | 10 +++------- .../home/pages/rulechain/rule-node-config.component.ts | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/ui-ngx/src/app/core/http/rule-chain.service.ts b/ui-ngx/src/app/core/http/rule-chain.service.ts index c7b7c04842..749fb39e72 100644 --- a/ui-ngx/src/app/core/http/rule-chain.service.ts +++ b/ui-ngx/src/app/core/http/rule-chain.service.ts @@ -53,7 +53,6 @@ export class RuleChainService { private ruleNodeComponentsMap: Map> = new Map>(); private ruleNodeConfigComponents: {[directive: string]: Type} = {}; - private systemRuleNodeConfigComponents: {[directive: string]: Type} = {}; constructor( private http: HttpClient, @@ -129,10 +128,7 @@ export class RuleChainService { } } - public getRuleNodeConfigComponent(directive: string, isSystemComponent = false): Type { - if (isSystemComponent) { - return this.systemRuleNodeConfigComponents[directive]; - } + public getRuleNodeConfigComponent(directive: string): Type { return this.ruleNodeConfigComponents[directive]; } @@ -185,7 +181,7 @@ export class RuleChainService { } public registerSystemRuleNodeConfigModule(module: any) { - this.systemRuleNodeConfigComponents = this.resourcesService.extractComponentsFromModule(module, true); + Object.assign(this.ruleNodeConfigComponents, this.resourcesService.extractComponentsFromModule(module, true)); } private loadRuleNodeComponents(ruleChainType: RuleChainType, config?: RequestConfig): Observable> { @@ -219,7 +215,7 @@ export class RuleChainService { Observable { const nodeDefinition = component.configurationDescriptor.nodeDefinition; const uiResources = nodeDefinition.uiResources; - if (uiResources && uiResources.length) { + if (!this.ruleNodeConfigComponents[nodeDefinition.configDirective] && uiResources && uiResources.length) { const commonResources = uiResources.filter((resource) => !resource.endsWith('.js')); const moduleResource = uiResources.find((resource) => resource.endsWith('.js')); const tasks: Observable[] = []; diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts index f6ed94991c..0a5057342f 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-config.component.ts @@ -212,7 +212,7 @@ export class RuleNodeConfigComponent implements ControlValueAccessor, OnDestroy this.changeScriptSubscription = null; } this.definedConfigContainer.clear(); - const component = this.ruleChainService.getRuleNodeConfigComponent(this.nodeDefinition.configDirective, !this.nodeDefinition.uiResources?.length); + const component = this.ruleChainService.getRuleNodeConfigComponent(this.nodeDefinition.configDirective); this.definedConfigComponentRef = this.definedConfigContainer.createComponent(component); this.definedConfigComponent = this.definedConfigComponentRef.instance; this.definedConfigComponent.ruleNodeId = this.ruleNodeId; From c3270e31f817de1281ab1192940595fc81af5af8 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Mon, 20 Jan 2025 12:34:31 +0200 Subject: [PATCH 12/13] UI: Add generic type to extractComponentsFromModule --- ui-ngx/src/app/core/services/resources.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/core/services/resources.service.ts b/ui-ngx/src/app/core/services/resources.service.ts index dcc6c3f8d0..72cea30a1a 100644 --- a/ui-ngx/src/app/core/services/resources.service.ts +++ b/ui-ngx/src/app/core/services/resources.service.ts @@ -267,9 +267,9 @@ export class ResourcesService { public extractComponentsFromModule(module: any, isCamelCaseSelector = false): ComponentsSelectorMap { const modulesWithComponents = this.extractModulesWithComponents(module); - const componentMap = {}; + const componentMap: ComponentsSelectorMap = {}; - const processComponents = (components: Array<ɵComponentDef>) => { + const processComponents = (components: Array<ɵComponentDef>) => { components.forEach(item => { let selector = extractSelectorFromComponent(item); if (isCamelCaseSelector) { From 6ba8aa90ab54b10e20353449c460da6e1486b6cf Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 22 Jan 2025 15:49:25 +0200 Subject: [PATCH 13/13] UI: Clear rule node components import --- .../rule-node/action/action-rule-node-config.module.ts | 4 ++-- .../rule-node/enrichment/enrichment-rule-node-core.module.ts | 4 ++-- .../rule-node/external/external-rule-node-config.module.ts | 4 ++-- .../rule-node/filter/filter-rule-node-config.module.ts | 4 ++-- .../rule-node/flow/flow-rule-node-config.module.ts | 4 ++-- .../transformation/transformation-rule-node-config.module.ts | 5 ++--- 6 files changed, 12 insertions(+), 13 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts index 17307cb341..5e7b53c02b 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/action/action-rule-node-config.module.ts @@ -14,9 +14,9 @@ /// limitations under the License. /// -import { NgModule, Type } from '@angular/core'; +import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { SharedModule } from '@shared/public-api'; import { HomeComponentsModule } from '@home/components/public-api'; import { AttributesConfigComponent } from './attributes-config.component'; import { TimeseriesConfigComponent } from './timeseries-config.component'; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/enrichment-rule-node-core.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/enrichment-rule-node-core.module.ts index 7d614ecd96..a20f387e34 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/enrichment/enrichment-rule-node-core.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/enrichment/enrichment-rule-node-core.module.ts @@ -14,9 +14,9 @@ /// limitations under the License. /// -import { NgModule, Type } from '@angular/core'; +import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { SharedModule } from '@shared/public-api'; import { CustomerAttributesConfigComponent } from './customer-attributes-config.component'; import { CommonRuleNodeConfigModule } from '../common/common-rule-node-config.module'; import { EntityDetailsConfigComponent } from './entity-details-config.component'; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts index c3c8c2ca2c..ef550d8460 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/external/external-rule-node-config.module.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { NgModule, Type } from '@angular/core'; +import { NgModule } from '@angular/core'; import { SnsConfigComponent } from './sns-config.component'; import { SqsConfigComponent } from './sqs-config.component'; import { PubSubConfigComponent } from './pubsub-config.component'; @@ -27,7 +27,7 @@ import { SendEmailConfigComponent } from './send-email-config.component'; import { AzureIotHubConfigComponent } from './azure-iot-hub-config.component'; import { SendSmsConfigComponent } from './send-sms-config.component'; import { CommonModule } from '@angular/common'; -import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { SharedModule } from '@shared/public-api'; import { HomeComponentsModule } from '@home/components/public-api'; import { CommonRuleNodeConfigModule } from '../common/common-rule-node-config.module'; import { SlackConfigComponent } from './slack-config.component'; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts index bb3636811b..2b26991a16 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/filter/filter-rule-node-config.module.ts @@ -14,9 +14,9 @@ /// limitations under the License. /// -import { NgModule, Type } from '@angular/core'; +import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { SharedModule } from '@shared/public-api'; import { CheckMessageConfigComponent } from './check-message-config.component'; import { CheckRelationConfigComponent } from './check-relation-config.component'; import { GpsGeoFilterConfigComponent } from './gps-geo-filter-config.component'; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts index 8a703ca9d2..95668cf19e 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/flow/flow-rule-node-config.module.ts @@ -14,9 +14,9 @@ /// limitations under the License. /// -import { NgModule, Type } from '@angular/core'; +import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { SharedModule } from '@shared/public-api'; import { RuleChainInputComponent } from './rule-chain-input.component'; import { RuleChainOutputComponent } from './rule-chain-output.component'; diff --git a/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts b/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts index 76ba7934d6..5104d3ac81 100644 --- a/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts +++ b/ui-ngx/src/app/modules/home/components/rule-node/transformation/transformation-rule-node-config.module.ts @@ -14,9 +14,9 @@ /// limitations under the License. /// -import { NgModule, Type } from '@angular/core'; +import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { IRuleNodeConfigurationComponent, SharedModule } from '@shared/public-api'; +import { SharedModule } from '@shared/public-api'; import { ChangeOriginatorConfigComponent } from './change-originator-config.component'; import { CommonRuleNodeConfigModule } from '../common/common-rule-node-config.module'; import { TransformScriptConfigComponent } from './script-config.component'; @@ -26,7 +26,6 @@ import { RenameKeysConfigComponent } from './rename-keys-config.component'; import { NodeJsonPathConfigComponent } from './node-json-path-config.component'; import { DeleteKeysConfigComponent } from './delete-keys-config.component'; import { DeduplicationConfigComponent } from './deduplication-config.component'; -import { ScriptConfigComponent } from '@home/components/rule-node/filter/script-config.component'; @NgModule({ declarations: [